summaryrefslogtreecommitdiff
path: root/src/atombios_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/atombios_output.c')
-rw-r--r--src/atombios_output.c2775
1 files changed, 0 insertions, 2775 deletions
diff --git a/src/atombios_output.c b/src/atombios_output.c
deleted file mode 100644
index 6c908870..00000000
--- a/src/atombios_output.c
+++ /dev/null
@@ -1,2775 +0,0 @@
-/*
- * Copyright © 2007 Red Hat, Inc.
- * Copyright 2007 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Dave Airlie <airlied@redhat.com>
- * Alex Deucher <alexdeucher@gmail.com>
- *
- */
-
-/*
- * avivo output handling functions.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-/* DPMS */
-#ifdef HAVE_XEXTPROTO_71
-#include <X11/extensions/dpmsconst.h>
-#else
-#define DPMS_SERVER
-#include <X11/extensions/dpms.h>
-#endif
-
-#include <unistd.h>
-
-#include "radeon.h"
-#include "radeon_reg.h"
-#include "radeon_macros.h"
-#include "radeon_atombios.h"
-
-#include "ati_pciids_gen.h"
-
-const char *device_name[12] = {
- "CRT1",
- "LCD1",
- "TV1",
- "DFP1",
- "CRT2",
- "LCD2",
- "TV2",
- "DFP2",
- "CV",
- "DFP3",
- "DFP4",
- "DFP5",
-};
-
-#define AUX_NATIVE_WRITE 0x8
-#define AUX_NATIVE_READ 0x9
-
-#define AUX_I2C_WRITE 0x0
-#define AUX_I2C_READ 0x1
-#define AUX_I2C_STATUS 0x2
-#define AUX_I2C_MOT 0x4
-
-#define DP_DPCD_REV 0x0
-#define DP_MAX_LINK_RATE 0x1
-#define DP_MAX_LANE_COUNT 0x2
-#define DP_MAX_DOWNSPREAD 0x3
-#define DP_NORP 0x4
-#define DP_DOWNSTREAMPORT_PRESENT 0x5
-#define DP_MAIN_LINK_CHANNEL_CONFIG 0x6
-#define DP_DP11_DOWNSTREAM_PORT_COUNT 0x7
-
-/* from intel i830_dp.h */
-#define DP_LINK_BW_SET 0x100
-//# define DP_LINK_BW_1_62 0x06
-//# define DP_LINK_BW_2_7 0x0a
-#define DP_LANE_COUNT_SET 0x101
-# define DP_LANE_COUNT_MASK 0x0f
-# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
-
-#define DP_TRAINING_PATTERN_SET 0x102
-
-# define DP_TRAINING_PATTERN_DISABLE 0
-# define DP_TRAINING_PATTERN_1 1
-# define DP_TRAINING_PATTERN_2 2
-# define DP_TRAINING_PATTERN_MASK 0x3
-
-# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
-# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
-# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
-# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
-# define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
-# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
-# define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
-
-# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
-# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
-# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
-# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
-
-#define DP_TRAINING_LANE0_SET 0x103
-#define DP_TRAINING_LANE1_SET 0x104
-#define DP_TRAINING_LANE2_SET 0x105
-#define DP_TRAINING_LANE3_SET 0x106
-# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
-# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
-# define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
-# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
-# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
-# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
-# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
-
-# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
-
-# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
-# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
-#define DP_DOWNSPREAD_CTRL 0x107
-# define DP_SPREAD_AMP_0_5 (1 << 4)
-
-#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
-# define DP_SET_ANSI_8B10B (1 << 0)
-
-#define DP_LANE0_1_STATUS 0x202
-#define DP_LANE2_3_STATUS 0x203
-
-# define DP_LANE_CR_DONE (1 << 0)
-# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
-# define DP_LANE_SYMBOL_LOCKED (1 << 2)
-
-#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
-#define DP_INTERLANE_ALIGN_DONE (1 << 0)
-#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
-#define DP_LINK_STATUS_UPDATED (1 << 7)
-
-#define DP_SINK_STATUS 0x205
-
-#define DP_RECEIVE_PORT_0_STATUS (1 << 0)
-#define DP_RECEIVE_PORT_1_STATUS (1 << 1)
-
-#define DP_ADJUST_REQUEST_LANE0_1 0x206
-#define DP_ADJUST_REQUEST_LANE2_3 0x207
-
-#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
-#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
-#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
-#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
-#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
-#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
-#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
-#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
-
-#define DP_LINK_STATUS_SIZE 6
-#define DP_LINK_CONFIGURATION_SIZE 9
-
-#define DP_SET_POWER_D0 0x1
-#define DP_SET_POWER_D3 0x2
-
-static void do_displayport_link_train(xf86OutputPtr output);
-
-static int
-atombios_output_dac_setup(xf86OutputPtr output, int action)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- radeon_tvout_ptr tvout = &radeon_output->tvout;
- DAC_ENCODER_CONTROL_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int index = 0, num = 0;
- int clock = radeon_output->pixel_clock;
-
- if (radeon_encoder == NULL)
- return ATOM_NOT_IMPLEMENTED;
-
- memset(&disp_data,0, sizeof(disp_data));
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_DAC1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
- index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
- num = 1;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DAC2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
- index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
- num = 2;
- break;
- }
-
- disp_data.ucAction =action;
-
- if (radeon_output->active_device & (ATOM_DEVICE_CRT_SUPPORT))
- disp_data.ucDacStandard = ATOM_DAC1_PS2;
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- disp_data.ucDacStandard = ATOM_DAC1_CV;
- else {
- switch (tvout->tvStd) {
- case TV_STD_PAL:
- case TV_STD_PAL_M:
- case TV_STD_SCART_PAL:
- case TV_STD_SECAM:
- case TV_STD_PAL_CN:
- disp_data.ucDacStandard = ATOM_DAC1_PAL;
- break;
- case TV_STD_NTSC:
- case TV_STD_NTSC_J:
- case TV_STD_PAL_60:
- default:
- disp_data.ucDacStandard = ATOM_DAC1_NTSC;
- break;
- }
- }
- disp_data.usPixelClock = cpu_to_le16(clock / 10);
-
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output DAC%d setup success\n", num);
- return ATOM_SUCCESS;
- }
-
- ErrorF("Output DAC%d setup failed\n", num);
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-static int
-atombios_output_tv_setup(xf86OutputPtr output, int action)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- radeon_tvout_ptr tvout = &radeon_output->tvout;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- TV_ENCODER_CONTROL_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int clock = radeon_output->pixel_clock;
-
- memset(&disp_data,0, sizeof(disp_data));
-
- disp_data.sTVEncoder.ucAction = action;
-
- if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_CV;
- else {
- switch (tvout->tvStd) {
- case TV_STD_NTSC:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
- break;
- case TV_STD_PAL:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
- break;
- case TV_STD_PAL_M:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
- break;
- case TV_STD_PAL_60:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
- break;
- case TV_STD_NTSC_J:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
- break;
- case TV_STD_SCART_PAL:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
- break;
- case TV_STD_SECAM:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
- break;
- case TV_STD_PAL_CN:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
- break;
- default:
- disp_data.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
- break;
- }
- }
-
- disp_data.sTVEncoder.usPixelClock = cpu_to_le16(clock / 10);
- data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output TV setup success\n");
- return ATOM_SUCCESS;
- }
-
- ErrorF("Output TV setup failed\n");
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-int
-atombios_external_tmds_setup(xf86OutputPtr output, int action)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- ScrnInfoPtr pScrn = output->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
- ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int clock = radeon_output->pixel_clock;
-
- memset(&disp_data,0, sizeof(disp_data));
-
- disp_data.sXTmdsEncoder.ucEnable = action;
-
- if (clock > 165000)
- disp_data.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
-
- if (pScrn->rgbBits == 8)
- disp_data.sXTmdsEncoder.ucMisc |= (1 << 1);
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("External TMDS setup success\n");
- return ATOM_SUCCESS;
- }
-
- ErrorF("External TMDS setup failed\n");
- return ATOM_NOT_IMPLEMENTED;
-}
-
-static int
-atombios_output_ddia_setup(xf86OutputPtr output, int action)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- DVO_ENCODER_CONTROL_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int clock = radeon_output->pixel_clock;
-
- memset(&disp_data,0, sizeof(disp_data));
-
- disp_data.sDVOEncoder.ucAction = action;
- disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(clock / 10);
-
- if (clock > 165000)
- disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("DDIA setup success\n");
- return ATOM_SUCCESS;
- }
-
- ErrorF("DDIA setup failed\n");
- return ATOM_NOT_IMPLEMENTED;
-}
-
-static int
-atombios_output_digital_setup(xf86OutputPtr output, int action)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- ScrnInfoPtr pScrn = output->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data;
- LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2;
- AtomBiosArgRec data;
- unsigned char *space;
- int index = 0;
- int major, minor;
- int lvds_misc = 0;
- int clock = radeon_output->pixel_clock;
-
- if (radeon_encoder == NULL)
- return ATOM_NOT_IMPLEMENTED;
-
- if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
- radeon_lvds_ptr lvds = (radeon_lvds_ptr)radeon_encoder->dev_priv;
- if (lvds == NULL)
- return ATOM_NOT_IMPLEMENTED;
- lvds_misc = lvds->lvds_misc;
- }
-
- memset(&disp_data,0, sizeof(disp_data));
- memset(&disp_data2,0, sizeof(disp_data2));
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_LVDS:
- index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
- index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
- index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
- else
- index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
- break;
- }
-
- atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
- /*ErrorF("table is %d %d\n", major, minor);*/
- switch (major) {
- case 0:
- case 1:
- case 2:
- switch (minor) {
- case 1:
- disp_data.ucMisc = 0;
- disp_data.ucAction = action;
- if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
- (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B))
- disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
- disp_data.usPixelClock = cpu_to_le16(clock / 10);
- if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
- if (lvds_misc & (1 << 0))
- disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL;
- if (lvds_misc & (1 << 1))
- disp_data.ucMisc |= (1 << 1);
- } else {
- if (radeon_output->linkb)
- disp_data.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
- if (clock > 165000)
- disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL;
- if (pScrn->rgbBits == 8)
- disp_data.ucMisc |= (1 << 1);
- }
- data.exec.pspace = &disp_data;
- break;
- case 2:
- case 3:
- disp_data2.ucMisc = 0;
- disp_data2.ucAction = action;
- if (minor == 3) {
- if (radeon_output->coherent_mode) {
- disp_data2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
- xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n");
- }
- }
- if ((radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
- (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_B))
- disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
- disp_data2.usPixelClock = cpu_to_le16(clock / 10);
- disp_data2.ucTruncate = 0;
- disp_data2.ucSpatial = 0;
- disp_data2.ucTemporal = 0;
- disp_data2.ucFRC = 0;
- if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
- if (lvds_misc & (1 << 0))
- disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
- if (lvds_misc & (1 << 5)) {
- disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
- if (lvds_misc & (1 << 1))
- disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
- }
- if (lvds_misc & (1 << 6)) {
- disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
- if (lvds_misc & (1 << 1))
- disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
- if (((lvds_misc >> 2) & 0x3) == 2)
- disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
- }
- } else {
- if (radeon_output->linkb)
- disp_data2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
- if (clock > 165000)
- disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
- }
- data.exec.pspace = &disp_data2;
- break;
- default:
- ErrorF("Unknown table version\n");
- exit(-1);
- }
- break;
- default:
- ErrorF("Unknown table version\n");
- exit(-1);
- }
-
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output digital setup success\n");
- return ATOM_SUCCESS;
- }
-
- ErrorF("Output digital setup failed\n");
- return ATOM_NOT_IMPLEMENTED;
-}
-
-static int
-atombios_maybe_hdmi_mode(xf86OutputPtr output)
-{
-#ifndef EDID_COMPLETE_RAWDATA
- /* there's no getting this right unless we have complete EDID */
- return ATOM_ENCODER_MODE_DVI;
-#else
- if (output && xf86MonitorIsHDMI(output->MonInfo))
- return ATOM_ENCODER_MODE_HDMI;
-
- return ATOM_ENCODER_MODE_DVI;
-#endif
-}
-
-int
-atombios_get_encoder_mode(xf86OutputPtr output)
-{
- ScrnInfoPtr pScrn = output->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
- /* DVI should really be atombios_maybe_hdmi_mode() as well */
- switch (radeon_output->ConnectorType) {
- case CONNECTOR_DVI_I:
- if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))
- return ATOM_ENCODER_MODE_DVI;
- else
- return ATOM_ENCODER_MODE_CRT;
- break;
- case CONNECTOR_DVI_D:
- default:
- return ATOM_ENCODER_MODE_DVI;
- break;
- case CONNECTOR_HDMI_TYPE_A:
- case CONNECTOR_HDMI_TYPE_B:
- if (IS_DCE4_VARIANT)
- return ATOM_ENCODER_MODE_DVI;
- else
- return atombios_maybe_hdmi_mode(output);
- break;
- case CONNECTOR_LVDS:
- return ATOM_ENCODER_MODE_LVDS;
- break;
- case CONNECTOR_DISPLAY_PORT:
- case CONNECTOR_EDP:
- if (radeon_output->MonType == MT_DP)
- return ATOM_ENCODER_MODE_DP;
- else {
- if (IS_DCE4_VARIANT)
- return ATOM_ENCODER_MODE_DVI;
- else
- return atombios_maybe_hdmi_mode(output);
- }
- break;
- case CONNECTOR_DVI_A:
- case CONNECTOR_VGA:
- case CONNECTOR_STV:
- case CONNECTOR_CTV:
- case CONNECTOR_DIN:
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- return ATOM_ENCODER_MODE_TV;
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- return ATOM_ENCODER_MODE_CV;
- else
- return ATOM_ENCODER_MODE_CRT;
- break;
- }
-
-}
-
-static const int dp_clocks[] = {
- 5400, // 1 lane, 1.62 Ghz
- 9000, // 1 lane, 2.70 Ghz
- 10800, // 2 lane, 1.62 Ghz
- 18000, // 2 lane, 2.70 Ghz
- 21600, // 4 lane, 1.62 Ghz
- 36000, // 4 lane, 2.70 Ghz
-};
-static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
-
-# define DP_LINK_BW_1_62 0x06
-# define DP_LINK_BW_2_7 0x0a
-static int radeon_dp_max_lane_count(xf86OutputPtr output);
-
-static int
-dp_lanes_for_mode_clock(xf86OutputPtr output, int mode_clock)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int i;
- int max_link_bw = radeon_output->dpcd[1];
- int max_lane_count = radeon_dp_max_lane_count(output);
-
- switch (max_link_bw) {
- case DP_LINK_BW_1_62:
- default:
- for (i = 0; i < num_dp_clocks; i++) {
- if (i % 2)
- continue;
- switch (max_lane_count) {
- case 1:
- if (i > 1)
- return 0;
- break;
- case 2:
- if (i > 3)
- return 0;
- break;
- case 4:
- default:
- break;
- }
- if (dp_clocks[i] > (mode_clock/10)) {
- if (i < 2)
- return 1;
- else if (i < 4)
- return 2;
- else
- return 4;
- }
- }
- break;
- case DP_LINK_BW_2_7:
- for (i = 0; i < num_dp_clocks; i++) {
- switch (max_lane_count) {
- case 1:
- if (i > 1)
- return 0;
- break;
- case 2:
- if (i > 3)
- return 0;
- break;
- case 4:
- default:
- break;
- }
- if (dp_clocks[i] > (mode_clock/10)) {
- if (i < 2)
- return 1;
- else if (i < 4)
- return 2;
- else
- return 4;
- }
- }
- break;
- }
-
- return 0;
-}
-
-static int
-dp_link_clock_for_mode_clock(xf86OutputPtr output, int mode_clock)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int i;
- int max_link_bw = radeon_output->dpcd[1];
- int max_lane_count = radeon_dp_max_lane_count(output);
-
- switch (max_link_bw) {
- case DP_LINK_BW_1_62:
- default:
- for (i = 0; i < num_dp_clocks; i++) {
- if (i % 2)
- continue;
- switch (max_lane_count) {
- case 1:
- if (i > 1)
- return 0;
- break;
- case 2:
- if (i > 3)
- return 0;
- break;
- case 4:
- default:
- break;
- }
- if (dp_clocks[i] > (mode_clock/10))
- return 16200;
- }
- break;
- case DP_LINK_BW_2_7:
- for (i = 0; i < num_dp_clocks; i++) {
- switch (max_lane_count) {
- case 1:
- if (i > 1)
- return 0;
- break;
- case 2:
- if (i > 3)
- return 0;
- break;
- case 4:
- default:
- break;
- }
- if (dp_clocks[i] > (mode_clock/10))
- return (i % 2) ? 27000 : 16200;
- }
- break;
- }
-
- return 0;
-}
-
-/*
- * DIG Encoder/Transmitter Setup
- *
- * DCE 3.0/3.1
- * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
- * Supports up to 3 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1 can drive UNIPHY link A or link B
- * DIG2 can drive UNIPHY link B or LVTMA
- *
- * DCE 3.2
- * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
- * Supports up to 5 digital outputs
- * - 2 DIG encoder blocks.
- * DIG1/2 can drive UNIPHY0/1/2 link A or link B
- *
- * DCE 4.0
- * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B).
- * Supports up to 6 digital outputs
- * - 6 DIG encoder blocks.
- * - DIG to PHY mapping is hardcoded
- * DIG1 drives UNIPHY0 link A, A+B
- * DIG2 drives UNIPHY0 link B
- * DIG3 drives UNIPHY1 link A, A+B
- * DIG4 drives UNIPHY1 link B
- * DIG5 drives UNIPHY2 link A, A+B
- * DIG6 drives UNIPHY2 link B
- *
- * Routing
- * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
- * Examples:
- * crtc0 -> dig2 -> LVTMA links A+B
- * crtc1 -> dig1 -> UNIPHY0 link B
- * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS
- * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI
- */
-
-union dig_encoder_control {
- DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
- DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
- DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
-};
-
-static int
-atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- union dig_encoder_control disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int index = 0, major, minor;
- int clock = radeon_output->pixel_clock;
-
- if (radeon_encoder == NULL)
- return ATOM_NOT_IMPLEMENTED;
-
- memset(&disp_data,0, sizeof(disp_data));
-
- if (IS_DCE4_VARIANT)
- index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
- else if (radeon_output->dig_encoder)
- index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
- else
- index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
-
- atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
- disp_data.v1.ucAction = action;
- disp_data.v1.usPixelClock = cpu_to_le16(clock / 10);
- disp_data.v1.ucEncoderMode = atombios_get_encoder_mode(output);
-
- if (disp_data.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
- if (dp_link_clock_for_mode_clock(output, clock) == 27000)
- disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
- disp_data.v1.ucLaneNum = dp_lanes_for_mode_clock(output, clock);
- } else if (clock > 165000)
- disp_data.v1.ucLaneNum = 8;
- else
- disp_data.v1.ucLaneNum = 4;
-
- if (IS_DCE4_VARIANT) {
- disp_data.v3.acConfig.ucDigSel = radeon_output->dig_encoder;
- disp_data.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
- } else {
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- disp_data.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- disp_data.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- disp_data.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
- break;
- }
- if (radeon_output->linkb)
- disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
- else
- disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
- }
-
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output DIG%d encoder setup success\n", radeon_output->dig_encoder);
- return ATOM_SUCCESS;
- }
-
- ErrorF("Output DIG%d setup failed\n", radeon_output->dig_encoder);
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-union dig_transmitter_control {
- DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
- DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
- DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
-};
-
-static int
-atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t lane_num, uint8_t lane_set)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- union dig_transmitter_control disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int index = 0, num = 0;
- int major, minor;
- int clock = radeon_output->pixel_clock;
-
- if (radeon_encoder == NULL)
- return ATOM_NOT_IMPLEMENTED;
-
- memset(&disp_data,0, sizeof(disp_data));
-
- if (IS_DCE32_VARIANT || IS_DCE4_VARIANT)
- index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
- else {
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
- break;
- }
- }
-
- atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
- disp_data.v1.ucAction = action;
- if (action == ATOM_TRANSMITTER_ACTION_INIT) {
- disp_data.v1.usInitInfo = radeon_output->connector_object_id;
- } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
- disp_data.v1.asMode.ucLaneSel = lane_num;
- disp_data.v1.asMode.ucLaneSet = lane_set;
- } else {
- if (radeon_output->MonType == MT_DP)
- disp_data.v1.usPixelClock =
- cpu_to_le16(dp_link_clock_for_mode_clock(output, clock));
- else if (clock > 165000)
- disp_data.v1.usPixelClock = cpu_to_le16((clock / 2) / 10);
- else
- disp_data.v1.usPixelClock = cpu_to_le16(clock / 10);
- }
-
- if (IS_DCE4_VARIANT) {
- if (radeon_output->MonType == MT_DP)
- disp_data.v3.ucLaneNum = dp_lanes_for_mode_clock(output, clock);
- else if (clock > 165000)
- disp_data.v3.ucLaneNum = 8;
- else
- disp_data.v3.ucLaneNum = 4;
-
- if (radeon_output->linkb) {
- disp_data.v3.acConfig.ucLinkSel = 1;
- disp_data.v2.acConfig.ucEncoderSel = 1;
- }
-
- // select the PLL for the UNIPHY
- if (radeon_output->MonType == MT_DP && info->dp_extclk)
- disp_data.v3.acConfig.ucRefClkSource = 2; /* ext clk */
- else
- disp_data.v3.acConfig.ucRefClkSource = radeon_output->pll_id;
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- disp_data.v3.acConfig.ucTransmitterSel = 0;
- num = 0;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- disp_data.v3.acConfig.ucTransmitterSel = 1;
- num = 1;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- disp_data.v3.acConfig.ucTransmitterSel = 2;
- num = 2;
- break;
- }
-
- if (radeon_output->MonType == MT_DP)
- disp_data.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
- else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
- if (radeon_output->coherent_mode)
- disp_data.v3.acConfig.fCoherentMode = 1;
- if (clock > 165000)
- disp_data.v3.acConfig.fDualLinkConnector = 1;
- }
- } else if (IS_DCE32_VARIANT) {
- if (radeon_output->dig_encoder)
- disp_data.v2.acConfig.ucEncoderSel = 1;
-
- if (radeon_output->linkb)
- disp_data.v2.acConfig.ucLinkSel = 1;
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- disp_data.v2.acConfig.ucTransmitterSel = 0;
- num = 0;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- disp_data.v2.acConfig.ucTransmitterSel = 1;
- num = 1;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- disp_data.v2.acConfig.ucTransmitterSel = 2;
- num = 2;
- break;
- }
-
- if (radeon_output->MonType == MT_DP)
- disp_data.v2.acConfig.fCoherentMode = 1; /* DP requires coherent */
- else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
- if (radeon_output->coherent_mode)
- disp_data.v2.acConfig.fCoherentMode = 1;
- if (clock > 165000)
- disp_data.v2.acConfig.fDualLinkConnector = 1;
- }
- } else {
- disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-
- if (radeon_output->dig_encoder)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
- else
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- if (info->IsIGP) {
- if (clock > 165000) {
- if (radeon_output->igp_lane_info & 0x3)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
- else if (radeon_output->igp_lane_info & 0xc)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
- } else {
- if (radeon_output->igp_lane_info & 0x1)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
- else if (radeon_output->igp_lane_info & 0x2)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
- else if (radeon_output->igp_lane_info & 0x4)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
- else if (radeon_output->igp_lane_info & 0x8)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
- }
- }
- break;
- }
- if (radeon_output->linkb)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
- else
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
-
- if (radeon_output->MonType == MT_DP)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; /* DP requires coherent */
- else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
- if (radeon_output->coherent_mode)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
- if (clock > 165000)
- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
- }
- }
-
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- if (IS_DCE32_VARIANT)
- ErrorF("Output UNIPHY%d transmitter setup success\n", num);
- else
- ErrorF("Output DIG%d transmitter setup success\n", num);
- return ATOM_SUCCESS;
- }
-
- ErrorF("Output DIG%d transmitter setup failed\n", num);
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-static void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn, RADEONCrtcPrivatePtr radeon_crtc)
-{
- RADEONInfoPtr info = RADEONPTR(pScrn);
- unsigned char *RADEONMMIO = info->MMIO;
- int index_reg = 0x6578, data_reg = 0x657c;
-
- index_reg += radeon_crtc->crtc_offset;
- data_reg += radeon_crtc->crtc_offset;
-
- OUTREG(0x659C + radeon_crtc->crtc_offset, 0x0);
- OUTREG(0x6594 + radeon_crtc->crtc_offset, 0x705);
- OUTREG(0x65A4 + radeon_crtc->crtc_offset, 0x10001);
- OUTREG(0x65D8 + radeon_crtc->crtc_offset, 0x0);
- OUTREG(0x65B0 + radeon_crtc->crtc_offset, 0x0);
- OUTREG(0x65C0 + radeon_crtc->crtc_offset, 0x0);
- OUTREG(0x65D4 + radeon_crtc->crtc_offset, 0x0);
- OUTREG(index_reg,0x0);
- OUTREG(data_reg,0x841880A8);
- OUTREG(index_reg,0x1);
- OUTREG(data_reg,0x84208680);
- OUTREG(index_reg,0x2);
- OUTREG(data_reg,0xBFF880B0);
- OUTREG(index_reg,0x100);
- OUTREG(data_reg,0x83D88088);
- OUTREG(index_reg,0x101);
- OUTREG(data_reg,0x84608680);
- OUTREG(index_reg,0x102);
- OUTREG(data_reg,0xBFF080D0);
- OUTREG(index_reg,0x200);
- OUTREG(data_reg,0x83988068);
- OUTREG(index_reg,0x201);
- OUTREG(data_reg,0x84A08680);
- OUTREG(index_reg,0x202);
- OUTREG(data_reg,0xBFF080F8);
- OUTREG(index_reg,0x300);
- OUTREG(data_reg,0x83588058);
- OUTREG(index_reg,0x301);
- OUTREG(data_reg,0x84E08660);
- OUTREG(index_reg,0x302);
- OUTREG(data_reg,0xBFF88120);
- OUTREG(index_reg,0x400);
- OUTREG(data_reg,0x83188040);
- OUTREG(index_reg,0x401);
- OUTREG(data_reg,0x85008660);
- OUTREG(index_reg,0x402);
- OUTREG(data_reg,0xBFF88150);
- OUTREG(index_reg,0x500);
- OUTREG(data_reg,0x82D88030);
- OUTREG(index_reg,0x501);
- OUTREG(data_reg,0x85408640);
- OUTREG(index_reg,0x502);
- OUTREG(data_reg,0xBFF88180);
- OUTREG(index_reg,0x600);
- OUTREG(data_reg,0x82A08018);
- OUTREG(index_reg,0x601);
- OUTREG(data_reg,0x85808620);
- OUTREG(index_reg,0x602);
- OUTREG(data_reg,0xBFF081B8);
- OUTREG(index_reg,0x700);
- OUTREG(data_reg,0x82608010);
- OUTREG(index_reg,0x701);
- OUTREG(data_reg,0x85A08600);
- OUTREG(index_reg,0x702);
- OUTREG(data_reg,0x800081F0);
- OUTREG(index_reg,0x800);
- OUTREG(data_reg,0x8228BFF8);
- OUTREG(index_reg,0x801);
- OUTREG(data_reg,0x85E085E0);
- OUTREG(index_reg,0x802);
- OUTREG(data_reg,0xBFF88228);
- OUTREG(index_reg,0x10000);
- OUTREG(data_reg,0x82A8BF00);
- OUTREG(index_reg,0x10001);
- OUTREG(data_reg,0x82A08CC0);
- OUTREG(index_reg,0x10002);
- OUTREG(data_reg,0x8008BEF8);
- OUTREG(index_reg,0x10100);
- OUTREG(data_reg,0x81F0BF28);
- OUTREG(index_reg,0x10101);
- OUTREG(data_reg,0x83608CA0);
- OUTREG(index_reg,0x10102);
- OUTREG(data_reg,0x8018BED0);
- OUTREG(index_reg,0x10200);
- OUTREG(data_reg,0x8148BF38);
- OUTREG(index_reg,0x10201);
- OUTREG(data_reg,0x84408C80);
- OUTREG(index_reg,0x10202);
- OUTREG(data_reg,0x8008BEB8);
- OUTREG(index_reg,0x10300);
- OUTREG(data_reg,0x80B0BF78);
- OUTREG(index_reg,0x10301);
- OUTREG(data_reg,0x85008C20);
- OUTREG(index_reg,0x10302);
- OUTREG(data_reg,0x8020BEA0);
- OUTREG(index_reg,0x10400);
- OUTREG(data_reg,0x8028BF90);
- OUTREG(index_reg,0x10401);
- OUTREG(data_reg,0x85E08BC0);
- OUTREG(index_reg,0x10402);
- OUTREG(data_reg,0x8018BE90);
- OUTREG(index_reg,0x10500);
- OUTREG(data_reg,0xBFB8BFB0);
- OUTREG(index_reg,0x10501);
- OUTREG(data_reg,0x86C08B40);
- OUTREG(index_reg,0x10502);
- OUTREG(data_reg,0x8010BE90);
- OUTREG(index_reg,0x10600);
- OUTREG(data_reg,0xBF58BFC8);
- OUTREG(index_reg,0x10601);
- OUTREG(data_reg,0x87A08AA0);
- OUTREG(index_reg,0x10602);
- OUTREG(data_reg,0x8010BE98);
- OUTREG(index_reg,0x10700);
- OUTREG(data_reg,0xBF10BFF0);
- OUTREG(index_reg,0x10701);
- OUTREG(data_reg,0x886089E0);
- OUTREG(index_reg,0x10702);
- OUTREG(data_reg,0x8018BEB0);
- OUTREG(index_reg,0x10800);
- OUTREG(data_reg,0xBED8BFE8);
- OUTREG(index_reg,0x10801);
- OUTREG(data_reg,0x89408940);
- OUTREG(index_reg,0x10802);
- OUTREG(data_reg,0xBFE8BED8);
- OUTREG(index_reg,0x20000);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x20001);
- OUTREG(data_reg,0x90008000);
- OUTREG(index_reg,0x20002);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x20003);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x20100);
- OUTREG(data_reg,0x80108000);
- OUTREG(index_reg,0x20101);
- OUTREG(data_reg,0x8FE0BF70);
- OUTREG(index_reg,0x20102);
- OUTREG(data_reg,0xBFE880C0);
- OUTREG(index_reg,0x20103);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x20200);
- OUTREG(data_reg,0x8018BFF8);
- OUTREG(index_reg,0x20201);
- OUTREG(data_reg,0x8F80BF08);
- OUTREG(index_reg,0x20202);
- OUTREG(data_reg,0xBFD081A0);
- OUTREG(index_reg,0x20203);
- OUTREG(data_reg,0xBFF88000);
- OUTREG(index_reg,0x20300);
- OUTREG(data_reg,0x80188000);
- OUTREG(index_reg,0x20301);
- OUTREG(data_reg,0x8EE0BEC0);
- OUTREG(index_reg,0x20302);
- OUTREG(data_reg,0xBFB082A0);
- OUTREG(index_reg,0x20303);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x20400);
- OUTREG(data_reg,0x80188000);
- OUTREG(index_reg,0x20401);
- OUTREG(data_reg,0x8E00BEA0);
- OUTREG(index_reg,0x20402);
- OUTREG(data_reg,0xBF8883C0);
- OUTREG(index_reg,0x20403);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x20500);
- OUTREG(data_reg,0x80188000);
- OUTREG(index_reg,0x20501);
- OUTREG(data_reg,0x8D00BE90);
- OUTREG(index_reg,0x20502);
- OUTREG(data_reg,0xBF588500);
- OUTREG(index_reg,0x20503);
- OUTREG(data_reg,0x80008008);
- OUTREG(index_reg,0x20600);
- OUTREG(data_reg,0x80188000);
- OUTREG(index_reg,0x20601);
- OUTREG(data_reg,0x8BC0BE98);
- OUTREG(index_reg,0x20602);
- OUTREG(data_reg,0xBF308660);
- OUTREG(index_reg,0x20603);
- OUTREG(data_reg,0x80008008);
- OUTREG(index_reg,0x20700);
- OUTREG(data_reg,0x80108000);
- OUTREG(index_reg,0x20701);
- OUTREG(data_reg,0x8A80BEB0);
- OUTREG(index_reg,0x20702);
- OUTREG(data_reg,0xBF0087C0);
- OUTREG(index_reg,0x20703);
- OUTREG(data_reg,0x80008008);
- OUTREG(index_reg,0x20800);
- OUTREG(data_reg,0x80108000);
- OUTREG(index_reg,0x20801);
- OUTREG(data_reg,0x8920BED0);
- OUTREG(index_reg,0x20802);
- OUTREG(data_reg,0xBED08920);
- OUTREG(index_reg,0x20803);
- OUTREG(data_reg,0x80008010);
- OUTREG(index_reg,0x30000);
- OUTREG(data_reg,0x90008000);
- OUTREG(index_reg,0x30001);
- OUTREG(data_reg,0x80008000);
- OUTREG(index_reg,0x30100);
- OUTREG(data_reg,0x8FE0BF90);
- OUTREG(index_reg,0x30101);
- OUTREG(data_reg,0xBFF880A0);
- OUTREG(index_reg,0x30200);
- OUTREG(data_reg,0x8F60BF40);
- OUTREG(index_reg,0x30201);
- OUTREG(data_reg,0xBFE88180);
- OUTREG(index_reg,0x30300);
- OUTREG(data_reg,0x8EC0BF00);
- OUTREG(index_reg,0x30301);
- OUTREG(data_reg,0xBFC88280);
- OUTREG(index_reg,0x30400);
- OUTREG(data_reg,0x8DE0BEE0);
- OUTREG(index_reg,0x30401);
- OUTREG(data_reg,0xBFA083A0);
- OUTREG(index_reg,0x30500);
- OUTREG(data_reg,0x8CE0BED0);
- OUTREG(index_reg,0x30501);
- OUTREG(data_reg,0xBF7884E0);
- OUTREG(index_reg,0x30600);
- OUTREG(data_reg,0x8BA0BED8);
- OUTREG(index_reg,0x30601);
- OUTREG(data_reg,0xBF508640);
- OUTREG(index_reg,0x30700);
- OUTREG(data_reg,0x8A60BEE8);
- OUTREG(index_reg,0x30701);
- OUTREG(data_reg,0xBF2087A0);
- OUTREG(index_reg,0x30800);
- OUTREG(data_reg,0x8900BF00);
- OUTREG(index_reg,0x30801);
- OUTREG(data_reg,0xBF008900);
-}
-
-static int
-atombios_output_yuv_setup(xf86OutputPtr output, Bool enable)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
- ENABLE_YUV_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- unsigned char *RADEONMMIO = info->MMIO;
- uint32_t temp, reg;
-
- if (info->ChipFamily >= CHIP_FAMILY_R600)
- reg = R600_BIOS_3_SCRATCH;
- else
- reg = RADEON_BIOS_3_SCRATCH;
-
- //fix up scratch reg handling
- temp = INREG(reg);
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- OUTREG(reg, (ATOM_S3_TV1_ACTIVE |
- (radeon_crtc->crtc_id << 18)));
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- OUTREG(reg, (ATOM_S3_CV_ACTIVE |
- (radeon_crtc->crtc_id << 24)));
- else
- OUTREG(reg, 0);
-
- memset(&disp_data, 0, sizeof(disp_data));
-
- if (enable)
- disp_data.ucEnable = ATOM_ENABLE;
- disp_data.ucCRTC = radeon_crtc->crtc_id;
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
-
- OUTREG(reg, temp);
-
- ErrorF("crtc %d YUV %s setup success\n", radeon_crtc->crtc_id, enable ? "enable" : "disable");
- return ATOM_SUCCESS;
- }
-
- OUTREG(reg, temp);
-
- ErrorF("crtc %d YUV %s setup failed\n", radeon_crtc->crtc_id, enable ? "enable" : "disable");
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-static int
-atombios_output_overscan_setup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- SET_CRTC_OVERSCAN_PS_ALLOCATION overscan_param;
- AtomBiosArgRec data;
- unsigned char *space;
- memset(&overscan_param, 0, sizeof(overscan_param));
-
- overscan_param.usOverscanRight = 0;
- overscan_param.usOverscanLeft = 0;
- overscan_param.usOverscanBottom = 0;
- overscan_param.usOverscanTop = 0;
- overscan_param.ucCRTC = radeon_crtc->crtc_id;
-
- if (radeon_output->Flags & RADEON_USE_RMX) {
- if (radeon_output->rmx_type == RMX_FULL) {
- overscan_param.usOverscanRight = 0;
- overscan_param.usOverscanLeft = 0;
- overscan_param.usOverscanBottom = 0;
- overscan_param.usOverscanTop = 0;
- } else if (radeon_output->rmx_type == RMX_CENTER) {
- overscan_param.usOverscanTop = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2;
- overscan_param.usOverscanBottom = (adjusted_mode->CrtcVDisplay - mode->CrtcVDisplay) / 2;
- overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2;
- overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - mode->CrtcHDisplay) / 2;
- } else if (radeon_output->rmx_type == RMX_ASPECT) {
- int a1 = mode->CrtcVDisplay * adjusted_mode->CrtcHDisplay;
- int a2 = adjusted_mode->CrtcVDisplay * mode->CrtcHDisplay;
-
- if (a1 > a2) {
- overscan_param.usOverscanLeft = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2;
- overscan_param.usOverscanRight = (adjusted_mode->CrtcHDisplay - (a2 / mode->CrtcVDisplay)) / 2;
- } else if (a2 > a1) {
- overscan_param.usOverscanLeft = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2;
- overscan_param.usOverscanRight = (adjusted_mode->CrtcVDisplay - (a1 / mode->CrtcHDisplay)) / 2;
- }
- }
- }
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &overscan_param;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Set CRTC %d Overscan success\n", radeon_crtc->crtc_id);
- return ATOM_SUCCESS ;
- }
-
- ErrorF("Set CRTC %d Overscan failed\n", radeon_crtc->crtc_id);
- return ATOM_NOT_IMPLEMENTED;
-}
-
-static int
-atombios_output_scaler_setup(xf86OutputPtr output)
-{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- radeon_tvout_ptr tvout = &radeon_output->tvout;
- RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
- ENABLE_SCALER_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
-
- if (!IS_AVIVO_VARIANT && radeon_crtc->crtc_id)
- return ATOM_SUCCESS;
-
- memset(&disp_data, 0, sizeof(disp_data));
-
- disp_data.ucScaler = radeon_crtc->crtc_id;
-
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
- switch (tvout->tvStd) {
- case TV_STD_NTSC:
- disp_data.ucTVStandard = ATOM_TV_NTSC;
- break;
- case TV_STD_PAL:
- disp_data.ucTVStandard = ATOM_TV_PAL;
- break;
- case TV_STD_PAL_M:
- disp_data.ucTVStandard = ATOM_TV_PALM;
- break;
- case TV_STD_PAL_60:
- disp_data.ucTVStandard = ATOM_TV_PAL60;
- break;
- case TV_STD_NTSC_J:
- disp_data.ucTVStandard = ATOM_TV_NTSCJ;
- break;
- case TV_STD_SCART_PAL:
- disp_data.ucTVStandard = ATOM_TV_PAL; /* ??? */
- break;
- case TV_STD_SECAM:
- disp_data.ucTVStandard = ATOM_TV_SECAM;
- break;
- case TV_STD_PAL_CN:
- disp_data.ucTVStandard = ATOM_TV_PALCN;
- break;
- default:
- disp_data.ucTVStandard = ATOM_TV_NTSC;
- break;
- }
- disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
- ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable);
- } else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) {
- disp_data.ucTVStandard = ATOM_TV_CV;
- disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
- ErrorF("Using CV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable);
- } else if (radeon_output->Flags & RADEON_USE_RMX) {
- ErrorF("Using RMX\n");
- if (radeon_output->rmx_type == RMX_FULL)
- disp_data.ucEnable = ATOM_SCALER_EXPANSION;
- else if (radeon_output->rmx_type == RMX_CENTER)
- disp_data.ucEnable = ATOM_SCALER_CENTER;
- else if (radeon_output->rmx_type == RMX_ASPECT)
- disp_data.ucEnable = ATOM_SCALER_EXPANSION;
- } else {
- ErrorF("Not using RMX\n");
- if (IS_AVIVO_VARIANT)
- disp_data.ucEnable = ATOM_SCALER_DISABLE;
- else
- disp_data.ucEnable = ATOM_SCALER_CENTER;
- }
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
- && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) {
- ErrorF("forcing TV scaler\n");
- atom_rv515_force_tv_scaler(output->scrn, radeon_crtc);
- }
- ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id);
- return ATOM_SUCCESS;
- }
-
- ErrorF("scaler %d setup failed\n", radeon_crtc->crtc_id);
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-void
-atombios_output_dpms(xf86OutputPtr output, int mode)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int index = 0;
- Bool is_dig = FALSE;
- unsigned char *RADEONMMIO = info->MMIO;
- uint32_t reg = 0;
-
- if (radeon_encoder == NULL)
- return;
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
- index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- is_dig = TRUE;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DVO1:
- case ENCODER_OBJECT_ID_INTERNAL_DDI:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
- index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_LVDS:
- index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
- if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
- index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
- else
- index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DAC1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
- if (IS_DCE32_VARIANT)
- index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
- else {
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
- else
- index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
- }
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DAC2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
- if (IS_DCE32_VARIANT)
- index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
- else {
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
- else
- index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
- }
- break;
- }
-
- switch (mode) {
- case DPMSModeOn:
- radeon_encoder->devices |= radeon_output->active_device;
- if (is_dig) {
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
- if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) ||
- (radeon_output->ConnectorType == CONNECTOR_EDP)) &&
- (radeon_output->MonType == MT_DP)) {
- do_displayport_link_train(output);
- if (IS_DCE4_VARIANT)
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_ON);
- }
- }
- else {
- disp_data.ucAction = ATOM_ENABLE;
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- /* workaround for DVOOutputControl on some RS690 systems */
- if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
- reg = INREG(RADEON_BIOS_3_SCRATCH);
- OUTREG(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
- }
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS)
- ErrorF("Output %s enable success\n",
- device_name[radeon_get_device_index(radeon_output->active_device)]);
- else
- ErrorF("Output %s enable failed\n",
- device_name[radeon_get_device_index(radeon_output->active_device)]);
- if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI)
- OUTREG(RADEON_BIOS_3_SCRATCH, reg);
- }
- /* at least for TV atom fails to reassociate the correct crtc source at dpms on */
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- atombios_set_output_crtc_source(output);
- break;
- case DPMSModeStandby:
- case DPMSModeSuspend:
- case DPMSModeOff:
- radeon_encoder->devices &= ~(radeon_output->active_device);
- if (!radeon_encoder->devices) {
- if (is_dig) {
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
- if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) ||
- (radeon_output->ConnectorType == CONNECTOR_EDP)) &&
- (radeon_output->MonType == MT_DP)) {
- if (IS_DCE4_VARIANT)
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
- }
- } else {
- disp_data.ucAction = ATOM_DISABLE;
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data)
- == ATOM_SUCCESS)
- ErrorF("Output %s disable success\n",
- device_name[radeon_get_device_index(radeon_output->active_device)]);
- else
- ErrorF("Output %s disable failed\n",
- device_name[radeon_get_device_index(radeon_output->active_device)]);
- }
- }
- break;
- }
-}
-
-union crtc_source_param {
- SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
- SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
-};
-
-void
-atombios_set_output_crtc_source(xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- AtomBiosArgRec data;
- unsigned char *space;
- union crtc_source_param args;
- int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
- int major, minor;
-
- if (radeon_encoder == NULL)
- return;
-
- memset(&args, 0, sizeof(args));
-
- atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
- /*ErrorF("select crtc source table is %d %d\n", major, minor);*/
-
- switch(major) {
- case 1:
- switch(minor) {
- case 0:
- case 1:
- default:
- if (IS_AVIVO_VARIANT)
- args.v1.ucCRTC = radeon_crtc->crtc_id;
- else {
- if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)
- args.v1.ucCRTC = radeon_crtc->crtc_id;
- else
- args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
- }
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
- args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_LVDS:
- case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
- if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT)
- args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
- else
- args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DVO1:
- case ENCODER_OBJECT_ID_INTERNAL_DDI:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
- args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DAC1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
- else
- args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DAC2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
- else
- args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
- break;
- }
- /*ErrorF("device sourced: 0x%x\n", args.v1.ucDevice);*/
- break;
- case 2:
- args.v2.ucCRTC = radeon_crtc->crtc_id;
- args.v2.ucEncodeMode = atombios_get_encoder_mode(output);
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- switch (radeon_output->dig_encoder) {
- case 0:
- args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
- break;
- case 1:
- args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
- break;
- case 2:
- args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
- break;
- case 3:
- args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
- break;
- case 4:
- args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
- break;
- case 5:
- args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
- break;
- }
- break;
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
- args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
- else
- args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
- args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
- else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
- args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
- else
- args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
- break;
- }
- /*ErrorF("device sourced: 0x%x\n", args.v2.ucEncoderID);*/
- break;
- }
- break;
- default:
- ErrorF("Unknown table version\n");
- exit(-1);
- }
-
- data.exec.pspace = &args;
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
-
- if (RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Set CRTC %d Source success\n", radeon_crtc->crtc_id);
- return;
- }
-
- ErrorF("Set CRTC Source failed\n");
- return;
-}
-
-static void
-atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- unsigned char *RADEONMMIO = info->MMIO;
-
- /* Funky macbooks */
- if ((info->Chipset == PCI_CHIP_RV530_71C5) &&
- (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) &&
- (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) {
- if (radeon_output->MonType == MT_LCD) {
- if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) {
- uint32_t lvtma_bit_depth_control = INREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
-
- lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
- lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
-
- OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
- }
- }
- }
-
- /* set scaler clears this on some chips */
- if (!(radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))) {
- if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE))
- OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN);
- }
-
- if (IS_DCE32_VARIANT &&
- (!IS_DCE4_VARIANT) &&
- (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- if (radeon_encoder == NULL)
- return;
- /* XXX: need to sort out why transmitter control table sometimes sets this to a
- * different golden value.
- */
- if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY2) {
- OUTREG(0x7ec4, 0x00824002);
- }
- }
-}
-
-void
-atombios_pick_dig_encoder(xf86OutputPtr output)
-{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(output->scrn);
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- radeon_encoder_ptr radeon_encoder = NULL;
- Bool is_lvtma = FALSE;
- int i, mode;
- uint32_t dig_enc_use_mask = 0;
-
- /* non digital encoders don't need a dig block */
- mode = atombios_get_encoder_mode(output);
- if (mode == ATOM_ENCODER_MODE_CRT ||
- mode == ATOM_ENCODER_MODE_TV ||
- mode == ATOM_ENCODER_MODE_CV)
- return;
-
- if (IS_DCE4_VARIANT) {
- radeon_encoder = radeon_get_encoder(output);
-
- if (IS_DCE41_VARIANT) {
- if (radeon_output->linkb)
- radeon_output->dig_encoder = 1;
- else
- radeon_output->dig_encoder = 0;
- } else {
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- if (radeon_output->linkb)
- radeon_output->dig_encoder = 1;
- else
- radeon_output->dig_encoder = 0;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- if (radeon_output->linkb)
- radeon_output->dig_encoder = 3;
- else
- radeon_output->dig_encoder = 2;
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- if (radeon_output->linkb)
- radeon_output->dig_encoder = 5;
- else
- radeon_output->dig_encoder = 4;
- break;
- default:
- ErrorF("Unknown encoder\n");
- break;
- }
- }
- return;
- }
-
- if (IS_DCE32_VARIANT) {
- RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private;
- radeon_output->dig_encoder = radeon_crtc->crtc_id;
- return;
- }
-
- for (i = 0; i < xf86_config->num_output; i++) {
- xf86OutputPtr test = xf86_config->output[i];
- RADEONOutputPrivatePtr radeon_test = test->driver_private;
- radeon_encoder = radeon_get_encoder(test);
-
- if (!radeon_encoder || !test->crtc)
- continue;
-
- if (output == test && radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA)
- is_lvtma = TRUE;
- if (output != test && (radeon_test->dig_encoder >= 0))
- dig_enc_use_mask |= (1 << radeon_test->dig_encoder);
-
- }
- if (is_lvtma) {
- if (dig_enc_use_mask & 0x2)
- ErrorF("Need digital encoder 2 for LVTMA and it isn't free - stealing\n");
- radeon_output->dig_encoder = 1;
- return;
- }
- if (!(dig_enc_use_mask & 1))
- radeon_output->dig_encoder = 0;
- else
- radeon_output->dig_encoder = 1;
-}
-void
-atombios_output_mode_set(xf86OutputPtr output,
- DisplayModePtr mode,
- DisplayModePtr adjusted_mode)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- if (radeon_encoder == NULL)
- return;
-
- radeon_output->pixel_clock = adjusted_mode->Clock;
- atombios_output_overscan_setup(output, mode, adjusted_mode);
- atombios_output_scaler_setup(output);
- atombios_set_output_crtc_source(output);
-
- if (IS_AVIVO_VARIANT && !IS_DCE4_VARIANT) {
- if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
- atombios_output_yuv_setup(output, TRUE);
- else
- atombios_output_yuv_setup(output, FALSE);
- }
-
- switch (radeon_encoder->encoder_id) {
- case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
- case ENCODER_OBJECT_ID_INTERNAL_LVDS:
- case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
- atombios_output_digital_setup(output, PANEL_ENCODER_ACTION_ENABLE);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
- case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- /* disable encoder and transmitter */
- /* setup and enable the encoder and transmitter */
- if (IS_DCE4_VARIANT) {
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_SETUP);
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
- } else {
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
- atombios_output_dig_encoder_setup(output, ATOM_DISABLE);
- atombios_output_dig_encoder_setup(output, ATOM_ENABLE);
-
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
- }
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DDI:
- atombios_output_ddia_setup(output, ATOM_ENABLE);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DVO1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
- atombios_external_tmds_setup(output, ATOM_ENABLE);
- break;
- case ENCODER_OBJECT_ID_INTERNAL_DAC1:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
- case ENCODER_OBJECT_ID_INTERNAL_DAC2:
- case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
- atombios_output_dac_setup(output, ATOM_ENABLE);
- if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
- if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
- atombios_output_tv_setup(output, ATOM_ENABLE);
- else
- atombios_output_tv_setup(output, ATOM_DISABLE);
- }
- break;
- }
- atombios_apply_output_quirks(output, adjusted_mode);
-}
-
-static AtomBiosResult
-atom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- DAC_LOAD_DETECTION_PS_ALLOCATION dac_data;
- AtomBiosArgRec data;
- unsigned char *space;
- int major, minor;
- int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
-
- atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
- dac_data.sDacload.ucMisc = 0;
-
- if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) {
- dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
- if (info->encoders[ATOM_DEVICE_CRT1_INDEX] &&
- ((info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
- (info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
- dac_data.sDacload.ucDacType = ATOM_DAC_A;
- else
- dac_data.sDacload.ucDacType = ATOM_DAC_B;
- } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) {
- dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
- if (info->encoders[ATOM_DEVICE_CRT2_INDEX] &&
- ((info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
- (info->encoders[ATOM_DEVICE_CRT2_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
- dac_data.sDacload.ucDacType = ATOM_DAC_A;
- else
- dac_data.sDacload.ucDacType = ATOM_DAC_B;
- } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) {
- dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
- if (info->encoders[ATOM_DEVICE_CV_INDEX] &&
- ((info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
- (info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
- dac_data.sDacload.ucDacType = ATOM_DAC_A;
- else
- dac_data.sDacload.ucDacType = ATOM_DAC_B;
- if (minor >= 3)
- dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
- } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
- dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
- if (info->encoders[ATOM_DEVICE_TV1_INDEX] &&
- ((info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
- (info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)))
- dac_data.sDacload.ucDacType = ATOM_DAC_A;
- else
- dac_data.sDacload.ucDacType = ATOM_DAC_B;
- if (minor >= 3)
- dac_data.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
- } else
- return ATOM_NOT_IMPLEMENTED;
-
- data.exec.index = index;
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &dac_data;
-
- if (RHDAtomBiosFunc(atomBIOS->pScrn, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Dac detection success\n");
- return ATOM_SUCCESS ;
- }
-
- ErrorF("DAC detection failed\n");
- return ATOM_NOT_IMPLEMENTED;
-}
-
-RADEONMonitorType
-atombios_dac_detect(xf86OutputPtr output)
-{
- ScrnInfoPtr pScrn = output->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
- unsigned char *RADEONMMIO = info->MMIO;
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONMonitorType MonType = MT_NONE;
- AtomBiosResult ret;
- RADEONSavePtr save = info->ModeReg;
-
- if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
- if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
- if (radeon_output->ConnectorType == CONNECTOR_STV)
- return MT_STV;
- else
- return MT_CTV;
- }
- }
-
- ret = atom_bios_dac_load_detect(info->atomBIOS, output);
- if (ret == ATOM_SUCCESS) {
- if (info->ChipFamily >= CHIP_FAMILY_R600)
- save->bios_0_scratch = INREG(R600_BIOS_0_SCRATCH);
- else
- save->bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH);
- /*ErrorF("DAC connect %08X\n", (unsigned int)save->bios_0_scratch);*/
-
- if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) {
- if (save->bios_0_scratch & ATOM_S0_CRT1_MASK)
- MonType = MT_CRT;
- } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) {
- if (save->bios_0_scratch & ATOM_S0_CRT2_MASK)
- MonType = MT_CRT;
- } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) {
- if (save->bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A))
- MonType = MT_CV;
- } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
- if (save->bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
- MonType = MT_CTV;
- else if (save->bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
- MonType = MT_STV;
- }
- }
-
- return MonType;
-}
-
-
-static inline int atom_dp_get_encoder_id(xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int ret = 0;
- if (radeon_output->dig_encoder)
- ret |= ATOM_DP_CONFIG_DIG2_ENCODER;
- else
- ret |= ATOM_DP_CONFIG_DIG1_ENCODER;
- if (radeon_output->linkb)
- ret |= ATOM_DP_CONFIG_LINK_B;
- else
- ret |= ATOM_DP_CONFIG_LINK_A;
- return ret;
-}
-
-union aux_channel_transaction {
- PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
- PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
-};
-
-Bool
-RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes,
- uint8_t *read_byte, uint8_t read_buf_len, uint8_t delay)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- union aux_channel_transaction args;
- AtomBiosArgRec data;
- unsigned char *space;
- unsigned char *base;
- int retry_count = 0;
-
- memset(&args, 0, sizeof(args));
- if (info->atomBIOS->fbBase)
- base = info->FB + info->atomBIOS->fbBase;
- else if (info->atomBIOS->scratchBase)
- base = (unsigned char *)info->atomBIOS->scratchBase;
- else
- return FALSE;
-
-retry:
- memcpy(base, req_bytes, num_bytes);
-
- args.v1.lpAuxRequest = 0;
- args.v1.lpDataOut = 16;
- args.v1.ucDataOutLen = 0;
- args.v1.ucChannelID = radeon_output->ucI2cId;
- args.v1.ucDelay = delay / 10; /* 10 usec */
- if (IS_DCE4_VARIANT)
- args.v2.ucHPD_ID = radeon_output->hpd_id;
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &args;
-
- RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data);
- if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) {
- if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10)
- goto retry;
- ErrorF("failed to get auxch %02x%02x %02x %02x %02x after %d retries\n",
- req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], args.v1.ucReplyStatus, retry_count);
- return FALSE;
- }
- if (args.v1.ucDataOutLen && read_byte && read_buf_len) {
- if (read_buf_len < args.v1.ucDataOutLen) {
- ErrorF("%s: Buffer too small for return answer %d %d\n", __func__, read_buf_len, args.v1.ucDataOutLen);
- return FALSE;
- }
- {
- int len = read_buf_len < args.v1.ucDataOutLen ? read_buf_len : args.v1.ucDataOutLen;
- memcpy(read_byte, base+16, len);
- }
- }
- return TRUE;
-}
-
-static int
-RADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig, uint8_t lane_num)
-{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- DP_ENCODER_SERVICE_PARAMETERS args;
- AtomBiosArgRec data;
- unsigned char *space;
-
- memset(&args, 0, sizeof(args));
-
- args.ucLinkClock = 0;
- args.ucConfig = ucconfig;
- args.ucAction = action;
- args.ucLaneNum = lane_num;
- args.ucStatus = 0;
-
- data.exec.index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &args;
-
- RHDAtomBiosFunc(info->atomBIOS->pScrn, info->atomBIOS, ATOMBIOS_EXEC, &data);
-
- ErrorF("%s: %d %d\n", __func__, action, args.ucStatus);
- return args.ucStatus;
-}
-
-int RADEON_DP_GetSinkType(xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
- return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, radeon_output->ucI2cId, 0);
-}
-
-static Bool atom_dp_aux_native_write(xf86OutputPtr output, uint16_t address,
- uint8_t send_bytes, uint8_t *send)
-{
- uint8_t msg[20];
- uint8_t msg_len, dp_msg_len;
- int ret;
-
- dp_msg_len = 4;
- msg[0] = address;
- msg[1] = address >> 8;
- msg[2] = AUX_NATIVE_WRITE << 4;
- dp_msg_len += send_bytes;
- msg[3] = (dp_msg_len << 4)| (send_bytes - 1);
-
- if (0)
- ErrorF("writing %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], send_bytes, dp_msg_len);
- if (send_bytes > 16)
- return FALSE;
-
- memcpy(&msg[4], send, send_bytes);
- msg_len = 4 + send_bytes;
- ret = RADEONProcessAuxCH(output, msg, msg_len, NULL, 0, 0);
- return ret;
-}
-
-static Bool atom_dp_aux_native_read(xf86OutputPtr output, uint16_t address,
- uint8_t delay,
- uint8_t expected_bytes, uint8_t *read_p)
-{
- uint8_t msg[20];
- uint8_t msg_len, dp_msg_len;
- int ret;
-
- msg_len = 4;
- dp_msg_len = 4;
- msg[0] = address;
- msg[1] = address >> 8;
- msg[2] = AUX_NATIVE_READ << 4;
- msg[3] = (dp_msg_len) << 4;
- msg[3] |= expected_bytes - 1;
-
- if (0)
- ErrorF("reading %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], expected_bytes, dp_msg_len);
- ret = RADEONProcessAuxCH(output, msg, msg_len, read_p, expected_bytes, delay);
- return ret;
-}
-
-/* fill out the DPCD structure */
-void RADEON_DP_GetDPCD(xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- uint8_t msg[25];
- int ret;
-
- ret = atom_dp_aux_native_read(output, DP_DPCD_REV, 0, 8, msg);
- if (ret) {
- memcpy(radeon_output->dpcd, msg, 8);
- if (0) {
- int i;
- ErrorF("DPCD: ");
- for (i = 0; i < 8; i++)
- ErrorF("%02x ", radeon_output->dpcd[i]);
- ErrorF("\n");
- }
- ret = atom_dp_aux_native_read(output, DP_LINK_BW_SET, 0, 2, msg);
- if (0) {
- ErrorF("0x200: %02x %02x\n", msg[0], msg[1]);
- }
- return;
- }
- radeon_output->dpcd[0] = 0;
- return;
-}
-
-
-enum dp_aux_i2c_mode {
- dp_aux_i2c_start,
- dp_aux_i2c_write,
- dp_aux_i2c_read,
- dp_aux_i2c_stop,
-};
-
-
-static Bool atom_dp_aux_i2c_transaction(xf86OutputPtr output, uint16_t address,
- enum dp_aux_i2c_mode mode,
- uint8_t write_byte, uint8_t *read_byte)
-{
- uint8_t msg[8], msg_len, dp_msg_len;
- int ret;
- int auxch_cmd = 0;
-
- memset(msg, 0, 8);
-
- if (mode != dp_aux_i2c_stop)
- auxch_cmd = AUX_I2C_MOT;
-
- if (address & 1)
- auxch_cmd |= AUX_I2C_READ;
- else
- auxch_cmd |= AUX_I2C_WRITE;
-
- msg[2] = auxch_cmd << 4;
-
- msg[4] = 0;
- msg[0] = (address >> 1);
- msg[1] = (address >> 9);
-
- msg_len = 4;
- dp_msg_len = 3;
- switch (mode) {
- case dp_aux_i2c_read:
- /* bottom bits is byte count - 1 so for 1 byte == 0 */
- dp_msg_len += 1;
- break;
- case dp_aux_i2c_write:
- dp_msg_len += 2;
- msg[4] = write_byte;
- msg_len++;
- break;
- default:
- break;
- }
- msg[3] = dp_msg_len << 4;
-
- ret = RADEONProcessAuxCH(output, msg, msg_len, read_byte, 1, 0);
- return ret;
-}
-
-static Bool
-atom_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr)
-{
- I2CBusPtr bus = dev->pI2CBus;
- xf86OutputPtr output = bus->DriverPrivate.ptr;
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int ret;
-
- radeon_output->dp_i2c_addr = addr;
- radeon_output->dp_i2c_running = TRUE;
-
- /* call i2c start */
- ret = atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
- dp_aux_i2c_start, 0, NULL);
-
- return ret;
-}
-static Bool
-atom_dp_i2c_start(I2CBusPtr bus, int timeout)
-{
- ErrorF("%s\n", __func__);
- return TRUE;
-}
-
-static void
-atom_dp_i2c_stop(I2CDevPtr dev)
-{
- I2CBusPtr bus = dev->pI2CBus;
- xf86OutputPtr output = bus->DriverPrivate.ptr;
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
- if (radeon_output->dp_i2c_running)
- atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
- dp_aux_i2c_stop, 0, NULL);
- radeon_output->dp_i2c_running = FALSE;
-}
-
-
-static Bool
-atom_dp_i2c_put_byte(I2CDevPtr dev, I2CByte byte)
-{
- I2CBusPtr bus = dev->pI2CBus;
- xf86OutputPtr output = bus->DriverPrivate.ptr;
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- Bool ret;
-
- ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
- dp_aux_i2c_write, byte, NULL));
- return ret;
-}
-
-static Bool
-atom_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last)
-{
- I2CBusPtr bus = dev->pI2CBus;
- xf86OutputPtr output = bus->DriverPrivate.ptr;
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- Bool ret;
-
- ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
- dp_aux_i2c_read, 0, byte_ret));
- return ret;
-}
-
-Bool
-RADEON_DP_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, xf86OutputPtr output)
-{
- I2CBusPtr pI2CBus;
-
- pI2CBus = xf86CreateI2CBusRec();
- if (!pI2CBus) return FALSE;
-
- pI2CBus->BusName = name;
- pI2CBus->scrnIndex = pScrn->scrnIndex;
- pI2CBus->I2CGetByte = atom_dp_i2c_get_byte;
- pI2CBus->I2CPutByte = atom_dp_i2c_put_byte;
- pI2CBus->I2CAddress = atom_dp_i2c_address;
- pI2CBus->I2CStart = atom_dp_i2c_start;
- pI2CBus->I2CStop = atom_dp_i2c_stop;
- pI2CBus->DriverPrivate.ptr = output;
-
- /*
- * These were set incorrectly in the server pre-1.3, Having
- * duplicate settings is sub-optimal, but this lets the driver
- * work with older servers
- */
- pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
- pI2CBus->StartTimeout = 550;
- pI2CBus->BitTimeout = 40;
- pI2CBus->AcknTimeout = 40;
- pI2CBus->RiseFallTime = 20;
-
- if (!xf86I2CBusInit(pI2CBus))
- return FALSE;
-
- *bus_ptr = pI2CBus;
- return TRUE;
-}
-
-
-static uint8_t dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int r)
-{
- return link_status[r - DP_LANE0_1_STATUS];
-}
-
-static uint8_t dp_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane)
-{
- int i = DP_LANE0_1_STATUS + (lane >> 1);
- int s = (lane & 1) * 4;
- uint8_t l = dp_link_status(link_status, i);
- return (l >> s) & 0xf;
-}
-
-static Bool dp_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
-{
- int lane;
-
- uint8_t lane_status;
-
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = dp_get_lane_status(link_status, lane);
- if ((lane_status & DP_LANE_CR_DONE) == 0)
- return FALSE;
- }
- return TRUE;
-}
-
-
-/* Check to see if channel eq is done on all channels */
-#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
- DP_LANE_CHANNEL_EQ_DONE|\
- DP_LANE_SYMBOL_LOCKED)
-static Bool
-dp_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
-{
- uint8_t lane_align;
- uint8_t lane_status;
- int lane;
-
- lane_align = dp_link_status(link_status,
- DP_LANE_ALIGN_STATUS_UPDATED);
- if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
- return FALSE;
- for (lane = 0; lane < lane_count; lane++) {
- lane_status = dp_get_lane_status(link_status, lane);
- if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * Fetch AUX CH registers 0x202 - 0x207 which contain
- * link status information
- */
-static Bool
-atom_dp_get_link_status(xf86OutputPtr output,
- uint8_t link_status[DP_LINK_STATUS_SIZE])
-{
- ScrnInfoPtr pScrn = output->scrn;
- int ret;
- ret = atom_dp_aux_native_read(output, DP_LANE0_1_STATUS, 100,
- DP_LINK_STATUS_SIZE, link_status);
- if (!ret) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "dp link status failed\n");
- return FALSE;
- }
- ErrorF("link status %02x %02x %02x %02x %02x %02x\n", link_status[0], link_status[1],
- link_status[2], link_status[3], link_status[4], link_status[5]);
-
- return TRUE;
-}
-
-static uint8_t
-dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
- int lane)
-
-{
- int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
- int s = ((lane & 1) ?
- DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
- DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
- uint8_t l = dp_link_status(link_status, i);
-
- return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
-}
-
-static uint8_t
-dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
- int lane)
-{
- int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
- int s = ((lane & 1) ?
- DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
- DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
- uint8_t l = dp_link_status(link_status, i);
-
- return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
-}
-
-static char *voltage_names[] = {
- "0.4V", "0.6V", "0.8V", "1.2V"
-};
-static char *pre_emph_names[] = {
- "0dB", "3.5dB", "6dB", "9.5dB"
-};
-
-/*
- * These are source-specific values; current Intel hardware supports
- * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
- */
-#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200
-
-static uint8_t
-dp_pre_emphasis_max(uint8_t voltage_swing)
-{
- switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_600:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_800:
- return DP_TRAIN_PRE_EMPHASIS_3_5;
- case DP_TRAIN_VOLTAGE_SWING_1200:
- default:
- return DP_TRAIN_PRE_EMPHASIS_0;
- }
-}
-
-static void dp_set_training(xf86OutputPtr output, uint8_t training)
-{
- atom_dp_aux_native_write(output, DP_TRAINING_PATTERN_SET, 1, &training);
-}
-
-static void dp_set_power(xf86OutputPtr output, uint8_t power_state)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
-
- if (radeon_output->dpcd[0] >= 0x11) {
- atom_dp_aux_native_write(output, 0x600, 1, &power_state);
- }
-}
-
-static void
-dp_get_adjust_train(xf86OutputPtr output,
- uint8_t link_status[DP_LINK_STATUS_SIZE],
- int lane_count,
- uint8_t train_set[4])
-{
- ScrnInfoPtr pScrn = output->scrn;
- uint8_t v = 0;
- uint8_t p = 0;
- int lane;
-
- for (lane = 0; lane < lane_count; lane++) {
- uint8_t this_v = dp_get_adjust_request_voltage(link_status, lane);
- uint8_t this_p = dp_get_adjust_request_pre_emphasis(link_status, lane);
-
- if (0) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "requested signal parameters: lane %d voltage %s pre_emph %s\n",
- lane,
- voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
- pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
- }
- if (this_v > v)
- v = this_v;
- if (this_p > p)
- p = this_p;
- }
-
- if (v >= DP_VOLTAGE_MAX)
- v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
-
- if (p >= dp_pre_emphasis_max(v))
- p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
- if (0) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "using signal parameters: voltage %s pre_emph %s\n",
- voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
- pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
- }
- for (lane = 0; lane < 4; lane++)
- train_set[lane] = v | p;
-}
-
-static int radeon_dp_max_lane_count(xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int max_lane_count = 4;
-
- if (radeon_output->dpcd[0] >= 0x11) {
- max_lane_count = radeon_output->dpcd[2] & 0x1f;
- switch(max_lane_count) {
- case 1: case 2: case 4:
- break;
- default:
- max_lane_count = 4;
- }
- }
- return max_lane_count;
-}
-
-Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int clock = adjusted_mode->Clock;
-
- radeon_output->dp_lane_count = dp_lanes_for_mode_clock(output, clock);
- radeon_output->dp_clock = dp_link_clock_for_mode_clock(output, clock);
- if (!radeon_output->dp_lane_count || !radeon_output->dp_clock)
- return FALSE;
- return TRUE;
-}
-
-static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4])
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int i;
- for (i = 0; i < radeon_output->dp_lane_count; i++)
- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, i, train_set[i]);
-
- atom_dp_aux_native_write(output, DP_TRAINING_LANE0_SET, radeon_output->dp_lane_count, train_set);
-}
-
-static void do_displayport_link_train(xf86OutputPtr output)
-{
- ScrnInfoPtr pScrn = output->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int enc_id = atom_dp_get_encoder_id(output);
- Bool clock_recovery;
- uint8_t link_status[DP_LINK_STATUS_SIZE];
- uint8_t tries, voltage, ss_cntl;
- uint8_t train_set[4];
- int i;
- Bool channel_eq;
- uint8_t dp_link_configuration[DP_LINK_CONFIGURATION_SIZE];
-
- memset(train_set, 0, 4);
-
- /* set up link configuration */
- memset(dp_link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
-
- if (radeon_output->dp_clock == 27000)
- dp_link_configuration[0] = DP_LINK_BW_2_7;
- else
- dp_link_configuration[0] = DP_LINK_BW_1_62;
- dp_link_configuration[1] = radeon_output->dp_lane_count;
-
- if (radeon_output->dpcd[0] >= 0x11) {
- dp_link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
- }
-
- /* power up to D0 */
- dp_set_power(output, DP_SET_POWER_D0);
-
- /* disable training */
- dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
-
- /* write link rate / num / eh framing */
- atom_dp_aux_native_write(output, DP_LINK_BW_SET, 2,
- dp_link_configuration);
-
- /* write ss cntl */
- ss_cntl = 0;
- atom_dp_aux_native_write(output, DP_DOWNSPREAD_CTRL, 1,
- &ss_cntl);
-
- /* start local training start */
- if (IS_DCE4_VARIANT) {
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1);
- } else {
- RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0);
- RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 0);
- }
-
- usleep(400);
- dp_set_training(output, DP_TRAINING_PATTERN_1);
- dp_update_dpvs_emph(output, train_set);
-
- /* loop around doing configuration reads and DP encoder setups */
- clock_recovery = FALSE;
- tries = 0;
- voltage = 0xff;
- for (;;) {
- usleep(100);
- if (!atom_dp_get_link_status(output, link_status))
- break;
-
- if (dp_clock_recovery_ok(link_status, radeon_output->dp_lane_count)) {
- clock_recovery = TRUE;
- break;
- }
-
- for (i = 0; i < radeon_output->dp_lane_count; i++)
- if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
- break;
- if (i == radeon_output->dp_lane_count) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "clock recovery reached max voltage\n");
- break;
- }
-
- /* Check to see if we've tried the same voltage 5 times */
- if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
- ++tries;
- if (tries == 5) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "clock recovery tried 5 times\n");
- break;
- }
- } else
- tries = 0;
-
- voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-
- dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set);
- dp_update_dpvs_emph(output, train_set);
-
- }
-
- if (!clock_recovery)
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "clock recovery failed\n");
-
- /* channel equalization */
- tries = 0;
- channel_eq = FALSE;
- dp_set_training(output, DP_TRAINING_PATTERN_2);
- if (IS_DCE4_VARIANT)
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2);
- else
- RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 1);
-
- for (;;) {
- usleep(400);
- if (!atom_dp_get_link_status(output, link_status))
- break;
-
- if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count)) {
- channel_eq = TRUE;
- break;
- }
-
- /* Try 5 times */
- if (tries > 5) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "channel eq failed: 5 tries\n");
- break;
- }
-
- /* Compute new train_set as requested by target */
- dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set);
- dp_update_dpvs_emph(output, train_set);
-
- ++tries;
- }
-
- if (!channel_eq)
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "channel eq failed\n");
-
- dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
- if (IS_DCE4_VARIANT)
- atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
- else
- RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, enc_id, 0);
-
-}
-