1771fe6b9SJerome Glisse /* 2771fe6b9SJerome Glisse * Copyright 2007-8 Advanced Micro Devices, Inc. 3771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc. 4771fe6b9SJerome Glisse * 5771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a 6771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"), 7771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation 8771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the 10771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions: 11771fe6b9SJerome Glisse * 12771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in 13771fe6b9SJerome Glisse * all copies or substantial portions of the Software. 14771fe6b9SJerome Glisse * 15771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE. 22771fe6b9SJerome Glisse * 23771fe6b9SJerome Glisse * Authors: Dave Airlie 24771fe6b9SJerome Glisse * Alex Deucher 25771fe6b9SJerome Glisse */ 26771fe6b9SJerome Glisse #include "drmP.h" 27771fe6b9SJerome Glisse #include "drm_crtc_helper.h" 28771fe6b9SJerome Glisse #include "radeon_drm.h" 29771fe6b9SJerome Glisse #include "radeon.h" 30771fe6b9SJerome Glisse #include "atom.h" 31771fe6b9SJerome Glisse 32771fe6b9SJerome Glisse extern int atom_debug; 33771fe6b9SJerome Glisse 34771fe6b9SJerome Glisse uint32_t 35771fe6b9SJerome Glisse radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac) 36771fe6b9SJerome Glisse { 37771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 38771fe6b9SJerome Glisse uint32_t ret = 0; 39771fe6b9SJerome Glisse 40771fe6b9SJerome Glisse switch (supported_device) { 41771fe6b9SJerome Glisse case ATOM_DEVICE_CRT1_SUPPORT: 42771fe6b9SJerome Glisse case ATOM_DEVICE_TV1_SUPPORT: 43771fe6b9SJerome Glisse case ATOM_DEVICE_TV2_SUPPORT: 44771fe6b9SJerome Glisse case ATOM_DEVICE_CRT2_SUPPORT: 45771fe6b9SJerome Glisse case ATOM_DEVICE_CV_SUPPORT: 46771fe6b9SJerome Glisse switch (dac) { 47771fe6b9SJerome Glisse case 1: /* dac a */ 48771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS300) || 49771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 50771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) 51771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 52771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 53771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 54771fe6b9SJerome Glisse else 55771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 56771fe6b9SJerome Glisse break; 57771fe6b9SJerome Glisse case 2: /* dac b */ 58771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 59771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 60771fe6b9SJerome Glisse else { 61771fe6b9SJerome Glisse /*if (rdev->family == CHIP_R200) 62771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 63771fe6b9SJerome Glisse else*/ 64771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 65771fe6b9SJerome Glisse } 66771fe6b9SJerome Glisse break; 67771fe6b9SJerome Glisse case 3: /* external dac */ 68771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 69771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 70771fe6b9SJerome Glisse else 71771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 72771fe6b9SJerome Glisse break; 73771fe6b9SJerome Glisse } 74771fe6b9SJerome Glisse break; 75771fe6b9SJerome Glisse case ATOM_DEVICE_LCD1_SUPPORT: 76771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 77771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 78771fe6b9SJerome Glisse else 79771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 80771fe6b9SJerome Glisse break; 81771fe6b9SJerome Glisse case ATOM_DEVICE_DFP1_SUPPORT: 82771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS300) || 83771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 84771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) 85771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 86771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 87771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 88771fe6b9SJerome Glisse else 89771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 90771fe6b9SJerome Glisse break; 91771fe6b9SJerome Glisse case ATOM_DEVICE_LCD2_SUPPORT: 92771fe6b9SJerome Glisse case ATOM_DEVICE_DFP2_SUPPORT: 93771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS600) || 94771fe6b9SJerome Glisse (rdev->family == CHIP_RS690) || 95771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) 96771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 97771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 98771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 99771fe6b9SJerome Glisse else 100771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 101771fe6b9SJerome Glisse break; 102771fe6b9SJerome Glisse case ATOM_DEVICE_DFP3_SUPPORT: 103771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 104771fe6b9SJerome Glisse break; 105771fe6b9SJerome Glisse } 106771fe6b9SJerome Glisse 107771fe6b9SJerome Glisse return ret; 108771fe6b9SJerome Glisse } 109771fe6b9SJerome Glisse 110771fe6b9SJerome Glisse void 111771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev) 112771fe6b9SJerome Glisse { 113771fe6b9SJerome Glisse struct drm_connector *connector; 114771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 115771fe6b9SJerome Glisse struct drm_encoder *encoder; 116771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 117771fe6b9SJerome Glisse 118771fe6b9SJerome Glisse /* walk the list and link encoders to connectors */ 119771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 120771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 121771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 122771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 123771fe6b9SJerome Glisse if (radeon_encoder->devices & radeon_connector->devices) 124771fe6b9SJerome Glisse drm_mode_connector_attach_encoder(connector, encoder); 125771fe6b9SJerome Glisse } 126771fe6b9SJerome Glisse } 127771fe6b9SJerome Glisse } 128771fe6b9SJerome Glisse 1294ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder) 1304ce001abSDave Airlie { 1314ce001abSDave Airlie struct drm_device *dev = encoder->dev; 1324ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1334ce001abSDave Airlie struct drm_connector *connector; 1344ce001abSDave Airlie 1354ce001abSDave Airlie list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1364ce001abSDave Airlie if (connector->encoder == encoder) { 1374ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1384ce001abSDave Airlie radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; 139f641e51eSDave Airlie DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n", 1404ce001abSDave Airlie radeon_encoder->active_device, radeon_encoder->devices, 1414ce001abSDave Airlie radeon_connector->devices, encoder->encoder_type); 1424ce001abSDave Airlie } 1434ce001abSDave Airlie } 1444ce001abSDave Airlie } 1454ce001abSDave Airlie 146771fe6b9SJerome Glisse static struct drm_connector * 147771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder) 148771fe6b9SJerome Glisse { 149771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 150771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 151771fe6b9SJerome Glisse struct drm_connector *connector; 152771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 153771fe6b9SJerome Glisse 154771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 155771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 156771fe6b9SJerome Glisse if (radeon_encoder->devices & radeon_connector->devices) 157771fe6b9SJerome Glisse return connector; 158771fe6b9SJerome Glisse } 159771fe6b9SJerome Glisse return NULL; 160771fe6b9SJerome Glisse } 161771fe6b9SJerome Glisse 162771fe6b9SJerome Glisse /* used for both atom and legacy */ 163771fe6b9SJerome Glisse void radeon_rmx_mode_fixup(struct drm_encoder *encoder, 164771fe6b9SJerome Glisse struct drm_display_mode *mode, 165771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 166771fe6b9SJerome Glisse { 167771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 168771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 169771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 170771fe6b9SJerome Glisse struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; 171771fe6b9SJerome Glisse 172771fe6b9SJerome Glisse if (mode->hdisplay < native_mode->panel_xres || 173771fe6b9SJerome Glisse mode->vdisplay < native_mode->panel_yres) { 174771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) { 175771fe6b9SJerome Glisse adjusted_mode->hdisplay = native_mode->panel_xres; 176771fe6b9SJerome Glisse adjusted_mode->vdisplay = native_mode->panel_yres; 177771fe6b9SJerome Glisse adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank; 178771fe6b9SJerome Glisse adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus; 179771fe6b9SJerome Glisse adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width; 180771fe6b9SJerome Glisse adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank; 181771fe6b9SJerome Glisse adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus; 182771fe6b9SJerome Glisse adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width; 183771fe6b9SJerome Glisse /* update crtc values */ 184771fe6b9SJerome Glisse drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 185771fe6b9SJerome Glisse /* adjust crtc values */ 186771fe6b9SJerome Glisse adjusted_mode->crtc_hdisplay = native_mode->panel_xres; 187771fe6b9SJerome Glisse adjusted_mode->crtc_vdisplay = native_mode->panel_yres; 188771fe6b9SJerome Glisse adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank; 189771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus; 190771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width; 191771fe6b9SJerome Glisse adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank; 192771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus; 193771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width; 194771fe6b9SJerome Glisse } else { 195771fe6b9SJerome Glisse adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank; 196771fe6b9SJerome Glisse adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus; 197771fe6b9SJerome Glisse adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width; 198771fe6b9SJerome Glisse adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank; 199771fe6b9SJerome Glisse adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus; 200771fe6b9SJerome Glisse adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width; 201771fe6b9SJerome Glisse /* update crtc values */ 202771fe6b9SJerome Glisse drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 203771fe6b9SJerome Glisse /* adjust crtc values */ 204771fe6b9SJerome Glisse adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank; 205771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus; 206771fe6b9SJerome Glisse adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width; 207771fe6b9SJerome Glisse adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank; 208771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus; 209771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width; 210771fe6b9SJerome Glisse } 211771fe6b9SJerome Glisse adjusted_mode->flags = native_mode->flags; 212771fe6b9SJerome Glisse adjusted_mode->clock = native_mode->dotclock; 213771fe6b9SJerome Glisse } 214771fe6b9SJerome Glisse } 215771fe6b9SJerome Glisse 216c93bb85bSJerome Glisse 217771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, 218771fe6b9SJerome Glisse struct drm_display_mode *mode, 219771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 220771fe6b9SJerome Glisse { 221771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 222771fe6b9SJerome Glisse 223771fe6b9SJerome Glisse drm_mode_set_crtcinfo(adjusted_mode, 0); 224771fe6b9SJerome Glisse 225771fe6b9SJerome Glisse if (radeon_encoder->rmx_type != RMX_OFF) 226771fe6b9SJerome Glisse radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); 227771fe6b9SJerome Glisse 228771fe6b9SJerome Glisse /* hw bug */ 229771fe6b9SJerome Glisse if ((mode->flags & DRM_MODE_FLAG_INTERLACE) 230771fe6b9SJerome Glisse && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) 231771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; 232771fe6b9SJerome Glisse 233771fe6b9SJerome Glisse return true; 234771fe6b9SJerome Glisse } 235771fe6b9SJerome Glisse 236771fe6b9SJerome Glisse static void 237771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action) 238771fe6b9SJerome Glisse { 239771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 240771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 241771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 242771fe6b9SJerome Glisse DAC_ENCODER_CONTROL_PS_ALLOCATION args; 243771fe6b9SJerome Glisse int index = 0, num = 0; 244445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 245771fe6b9SJerome Glisse enum radeon_tv_std tv_std = TV_STD_NTSC; 246771fe6b9SJerome Glisse 247445282dbSDave Airlie if (dac_info->tv_std) 248445282dbSDave Airlie tv_std = dac_info->tv_std; 249445282dbSDave Airlie 250771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 251771fe6b9SJerome Glisse 252771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 253771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 254771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 255771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 256771fe6b9SJerome Glisse num = 1; 257771fe6b9SJerome Glisse break; 258771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 259771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 260771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 261771fe6b9SJerome Glisse num = 2; 262771fe6b9SJerome Glisse break; 263771fe6b9SJerome Glisse } 264771fe6b9SJerome Glisse 265771fe6b9SJerome Glisse args.ucAction = action; 266771fe6b9SJerome Glisse 2674ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 268771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PS2; 2694ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 270771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_CV; 271771fe6b9SJerome Glisse else { 272771fe6b9SJerome Glisse switch (tv_std) { 273771fe6b9SJerome Glisse case TV_STD_PAL: 274771fe6b9SJerome Glisse case TV_STD_PAL_M: 275771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 276771fe6b9SJerome Glisse case TV_STD_SECAM: 277771fe6b9SJerome Glisse case TV_STD_PAL_CN: 278771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PAL; 279771fe6b9SJerome Glisse break; 280771fe6b9SJerome Glisse case TV_STD_NTSC: 281771fe6b9SJerome Glisse case TV_STD_NTSC_J: 282771fe6b9SJerome Glisse case TV_STD_PAL_60: 283771fe6b9SJerome Glisse default: 284771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_NTSC; 285771fe6b9SJerome Glisse break; 286771fe6b9SJerome Glisse } 287771fe6b9SJerome Glisse } 288771fe6b9SJerome Glisse args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 289771fe6b9SJerome Glisse 290771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 291771fe6b9SJerome Glisse 292771fe6b9SJerome Glisse } 293771fe6b9SJerome Glisse 294771fe6b9SJerome Glisse static void 295771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action) 296771fe6b9SJerome Glisse { 297771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 298771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 299771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 300771fe6b9SJerome Glisse TV_ENCODER_CONTROL_PS_ALLOCATION args; 301771fe6b9SJerome Glisse int index = 0; 302445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 303771fe6b9SJerome Glisse enum radeon_tv_std tv_std = TV_STD_NTSC; 304771fe6b9SJerome Glisse 305445282dbSDave Airlie if (dac_info->tv_std) 306445282dbSDave Airlie tv_std = dac_info->tv_std; 307445282dbSDave Airlie 308771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 309771fe6b9SJerome Glisse 310771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 311771fe6b9SJerome Glisse 312771fe6b9SJerome Glisse args.sTVEncoder.ucAction = action; 313771fe6b9SJerome Glisse 3144ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 315771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 316771fe6b9SJerome Glisse else { 317771fe6b9SJerome Glisse switch (tv_std) { 318771fe6b9SJerome Glisse case TV_STD_NTSC: 319771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 320771fe6b9SJerome Glisse break; 321771fe6b9SJerome Glisse case TV_STD_PAL: 322771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 323771fe6b9SJerome Glisse break; 324771fe6b9SJerome Glisse case TV_STD_PAL_M: 325771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 326771fe6b9SJerome Glisse break; 327771fe6b9SJerome Glisse case TV_STD_PAL_60: 328771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 329771fe6b9SJerome Glisse break; 330771fe6b9SJerome Glisse case TV_STD_NTSC_J: 331771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 332771fe6b9SJerome Glisse break; 333771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 334771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 335771fe6b9SJerome Glisse break; 336771fe6b9SJerome Glisse case TV_STD_SECAM: 337771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 338771fe6b9SJerome Glisse break; 339771fe6b9SJerome Glisse case TV_STD_PAL_CN: 340771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 341771fe6b9SJerome Glisse break; 342771fe6b9SJerome Glisse default: 343771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 344771fe6b9SJerome Glisse break; 345771fe6b9SJerome Glisse } 346771fe6b9SJerome Glisse } 347771fe6b9SJerome Glisse 348771fe6b9SJerome Glisse args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 349771fe6b9SJerome Glisse 350771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 351771fe6b9SJerome Glisse 352771fe6b9SJerome Glisse } 353771fe6b9SJerome Glisse 354771fe6b9SJerome Glisse void 355771fe6b9SJerome Glisse atombios_external_tmds_setup(struct drm_encoder *encoder, int action) 356771fe6b9SJerome Glisse { 357771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 358771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 359771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 360771fe6b9SJerome Glisse ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args; 361771fe6b9SJerome Glisse int index = 0; 362771fe6b9SJerome Glisse 363771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 364771fe6b9SJerome Glisse 365771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 366771fe6b9SJerome Glisse 367771fe6b9SJerome Glisse args.sXTmdsEncoder.ucEnable = action; 368771fe6b9SJerome Glisse 369771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 370771fe6b9SJerome Glisse args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; 371771fe6b9SJerome Glisse 372771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8)*/ 373771fe6b9SJerome Glisse args.sXTmdsEncoder.ucMisc |= (1 << 1); 374771fe6b9SJerome Glisse 375771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 376771fe6b9SJerome Glisse 377771fe6b9SJerome Glisse } 378771fe6b9SJerome Glisse 379771fe6b9SJerome Glisse static void 380771fe6b9SJerome Glisse atombios_ddia_setup(struct drm_encoder *encoder, int action) 381771fe6b9SJerome Glisse { 382771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 383771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 384771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 385771fe6b9SJerome Glisse DVO_ENCODER_CONTROL_PS_ALLOCATION args; 386771fe6b9SJerome Glisse int index = 0; 387771fe6b9SJerome Glisse 388771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 389771fe6b9SJerome Glisse 390771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 391771fe6b9SJerome Glisse 392771fe6b9SJerome Glisse args.sDVOEncoder.ucAction = action; 393771fe6b9SJerome Glisse args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 394771fe6b9SJerome Glisse 395771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 396771fe6b9SJerome Glisse args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; 397771fe6b9SJerome Glisse 398771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 399771fe6b9SJerome Glisse 400771fe6b9SJerome Glisse } 401771fe6b9SJerome Glisse 402771fe6b9SJerome Glisse union lvds_encoder_control { 403771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 404771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 405771fe6b9SJerome Glisse }; 406771fe6b9SJerome Glisse 407771fe6b9SJerome Glisse static void 408771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action) 409771fe6b9SJerome Glisse { 410771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 411771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 412771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 413771fe6b9SJerome Glisse union lvds_encoder_control args; 414771fe6b9SJerome Glisse int index = 0; 415771fe6b9SJerome Glisse uint8_t frev, crev; 416771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 417771fe6b9SJerome Glisse struct drm_connector *connector; 418771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 419771fe6b9SJerome Glisse struct radeon_connector_atom_dig *dig_connector; 420771fe6b9SJerome Glisse 421771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 422771fe6b9SJerome Glisse if (!connector) 423771fe6b9SJerome Glisse return; 424771fe6b9SJerome Glisse 425771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 426771fe6b9SJerome Glisse 427771fe6b9SJerome Glisse if (!radeon_encoder->enc_priv) 428771fe6b9SJerome Glisse return; 429771fe6b9SJerome Glisse 430771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 431771fe6b9SJerome Glisse 432771fe6b9SJerome Glisse if (!radeon_connector->con_priv) 433771fe6b9SJerome Glisse return; 434771fe6b9SJerome Glisse 435771fe6b9SJerome Glisse dig_connector = radeon_connector->con_priv; 436771fe6b9SJerome Glisse 437771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 438771fe6b9SJerome Glisse 439771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 440771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 441771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 442771fe6b9SJerome Glisse break; 443771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 444771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 445771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 446771fe6b9SJerome Glisse break; 447771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 448771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 449771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 450771fe6b9SJerome Glisse else 451771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 452771fe6b9SJerome Glisse break; 453771fe6b9SJerome Glisse } 454771fe6b9SJerome Glisse 455771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 456771fe6b9SJerome Glisse 457771fe6b9SJerome Glisse switch (frev) { 458771fe6b9SJerome Glisse case 1: 459771fe6b9SJerome Glisse case 2: 460771fe6b9SJerome Glisse switch (crev) { 461771fe6b9SJerome Glisse case 1: 462771fe6b9SJerome Glisse args.v1.ucMisc = 0; 463771fe6b9SJerome Glisse args.v1.ucAction = action; 464771fe6b9SJerome Glisse if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) 465771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 466771fe6b9SJerome Glisse args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 467771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 468771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 0)) 469771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 470771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 1)) 471771fe6b9SJerome Glisse args.v1.ucMisc |= (1 << 1); 472771fe6b9SJerome Glisse } else { 473771fe6b9SJerome Glisse if (dig_connector->linkb) 474771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 475771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 476771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 477771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8) */ 478771fe6b9SJerome Glisse args.v1.ucMisc |= (1 << 1); 479771fe6b9SJerome Glisse } 480771fe6b9SJerome Glisse break; 481771fe6b9SJerome Glisse case 2: 482771fe6b9SJerome Glisse case 3: 483771fe6b9SJerome Glisse args.v2.ucMisc = 0; 484771fe6b9SJerome Glisse args.v2.ucAction = action; 485771fe6b9SJerome Glisse if (crev == 3) { 486771fe6b9SJerome Glisse if (dig->coherent_mode) 487771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 488771fe6b9SJerome Glisse } 489771fe6b9SJerome Glisse if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) 490771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 491771fe6b9SJerome Glisse args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 492771fe6b9SJerome Glisse args.v2.ucTruncate = 0; 493771fe6b9SJerome Glisse args.v2.ucSpatial = 0; 494771fe6b9SJerome Glisse args.v2.ucTemporal = 0; 495771fe6b9SJerome Glisse args.v2.ucFRC = 0; 496771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 497771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 0)) 498771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 499771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 5)) { 500771fe6b9SJerome Glisse args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 501771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 1)) 502771fe6b9SJerome Glisse args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 503771fe6b9SJerome Glisse } 504771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 6)) { 505771fe6b9SJerome Glisse args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 506771fe6b9SJerome Glisse if (dig->lvds_misc & (1 << 1)) 507771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 508771fe6b9SJerome Glisse if (((dig->lvds_misc >> 2) & 0x3) == 2) 509771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 510771fe6b9SJerome Glisse } 511771fe6b9SJerome Glisse } else { 512771fe6b9SJerome Glisse if (dig_connector->linkb) 513771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 514771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 515771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 516771fe6b9SJerome Glisse } 517771fe6b9SJerome Glisse break; 518771fe6b9SJerome Glisse default: 519771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 520771fe6b9SJerome Glisse break; 521771fe6b9SJerome Glisse } 522771fe6b9SJerome Glisse break; 523771fe6b9SJerome Glisse default: 524771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 525771fe6b9SJerome Glisse break; 526771fe6b9SJerome Glisse } 527771fe6b9SJerome Glisse 528771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 529771fe6b9SJerome Glisse 530771fe6b9SJerome Glisse } 531771fe6b9SJerome Glisse 532771fe6b9SJerome Glisse int 533771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder) 534771fe6b9SJerome Glisse { 535771fe6b9SJerome Glisse struct drm_connector *connector; 536771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 537771fe6b9SJerome Glisse 538771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 539771fe6b9SJerome Glisse if (!connector) 540771fe6b9SJerome Glisse return 0; 541771fe6b9SJerome Glisse 542771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 543771fe6b9SJerome Glisse 544771fe6b9SJerome Glisse switch (connector->connector_type) { 545771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVII: 546705af9c7SAlex Deucher case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ 547771fe6b9SJerome Glisse if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) 548771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 549771fe6b9SJerome Glisse else if (radeon_connector->use_digital) 550771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 551771fe6b9SJerome Glisse else 552771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 553771fe6b9SJerome Glisse break; 554771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVID: 555771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_HDMIA: 556771fe6b9SJerome Glisse default: 557771fe6b9SJerome Glisse if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) 558771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 559771fe6b9SJerome Glisse else 560771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 561771fe6b9SJerome Glisse break; 562771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_LVDS: 563771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_LVDS; 564771fe6b9SJerome Glisse break; 565771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DisplayPort: 566771fe6b9SJerome Glisse /*if (radeon_output->MonType == MT_DP) 567771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DP; 568771fe6b9SJerome Glisse else*/ 569771fe6b9SJerome Glisse if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) 570771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 571771fe6b9SJerome Glisse else 572771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 573771fe6b9SJerome Glisse break; 574771fe6b9SJerome Glisse case CONNECTOR_DVI_A: 575771fe6b9SJerome Glisse case CONNECTOR_VGA: 576771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 577771fe6b9SJerome Glisse break; 578771fe6b9SJerome Glisse case CONNECTOR_STV: 579771fe6b9SJerome Glisse case CONNECTOR_CTV: 580771fe6b9SJerome Glisse case CONNECTOR_DIN: 581771fe6b9SJerome Glisse /* fix me */ 582771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_TV; 583771fe6b9SJerome Glisse /*return ATOM_ENCODER_MODE_CV;*/ 584771fe6b9SJerome Glisse break; 585771fe6b9SJerome Glisse } 586771fe6b9SJerome Glisse } 587771fe6b9SJerome Glisse 588771fe6b9SJerome Glisse static void 589771fe6b9SJerome Glisse atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) 590771fe6b9SJerome Glisse { 591771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 592771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 593771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 594771fe6b9SJerome Glisse DIG_ENCODER_CONTROL_PS_ALLOCATION args; 595771fe6b9SJerome Glisse int index = 0, num = 0; 596771fe6b9SJerome Glisse uint8_t frev, crev; 597771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 598771fe6b9SJerome Glisse struct drm_connector *connector; 599771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 600771fe6b9SJerome Glisse struct radeon_connector_atom_dig *dig_connector; 601771fe6b9SJerome Glisse 602771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 603771fe6b9SJerome Glisse if (!connector) 604771fe6b9SJerome Glisse return; 605771fe6b9SJerome Glisse 606771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 607771fe6b9SJerome Glisse 608771fe6b9SJerome Glisse if (!radeon_connector->con_priv) 609771fe6b9SJerome Glisse return; 610771fe6b9SJerome Glisse 611771fe6b9SJerome Glisse dig_connector = radeon_connector->con_priv; 612771fe6b9SJerome Glisse 613771fe6b9SJerome Glisse if (!radeon_encoder->enc_priv) 614771fe6b9SJerome Glisse return; 615771fe6b9SJerome Glisse 616771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 617771fe6b9SJerome Glisse 618771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 619771fe6b9SJerome Glisse 620771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 621771fe6b9SJerome Glisse if (dig->dig_block) 622771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 623771fe6b9SJerome Glisse else 624771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 625771fe6b9SJerome Glisse num = dig->dig_block + 1; 626771fe6b9SJerome Glisse } else { 627771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 628771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 629771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 630771fe6b9SJerome Glisse num = 1; 631771fe6b9SJerome Glisse break; 632771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 633771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 634771fe6b9SJerome Glisse num = 2; 635771fe6b9SJerome Glisse break; 636771fe6b9SJerome Glisse } 637771fe6b9SJerome Glisse } 638771fe6b9SJerome Glisse 639771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 640771fe6b9SJerome Glisse 641771fe6b9SJerome Glisse args.ucAction = action; 642771fe6b9SJerome Glisse args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 643771fe6b9SJerome Glisse 644771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 645771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 646771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 647771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 648771fe6b9SJerome Glisse break; 649771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 650771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 651771fe6b9SJerome Glisse break; 652771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 653771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 654771fe6b9SJerome Glisse break; 655771fe6b9SJerome Glisse } 656771fe6b9SJerome Glisse } else { 657771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 658771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 659771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1; 660771fe6b9SJerome Glisse break; 661771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 662771fe6b9SJerome Glisse args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2; 663771fe6b9SJerome Glisse break; 664771fe6b9SJerome Glisse } 665771fe6b9SJerome Glisse } 666771fe6b9SJerome Glisse 667771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) { 668771fe6b9SJerome Glisse args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; 669771fe6b9SJerome Glisse args.ucLaneNum = 8; 670771fe6b9SJerome Glisse } else { 671771fe6b9SJerome Glisse if (dig_connector->linkb) 672771fe6b9SJerome Glisse args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 673771fe6b9SJerome Glisse else 674771fe6b9SJerome Glisse args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 675771fe6b9SJerome Glisse args.ucLaneNum = 4; 676771fe6b9SJerome Glisse } 677771fe6b9SJerome Glisse 678771fe6b9SJerome Glisse args.ucEncoderMode = atombios_get_encoder_mode(encoder); 679771fe6b9SJerome Glisse 680771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 681771fe6b9SJerome Glisse 682771fe6b9SJerome Glisse } 683771fe6b9SJerome Glisse 684771fe6b9SJerome Glisse union dig_transmitter_control { 685771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 686771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 687771fe6b9SJerome Glisse }; 688771fe6b9SJerome Glisse 689771fe6b9SJerome Glisse static void 690771fe6b9SJerome Glisse atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) 691771fe6b9SJerome Glisse { 692771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 693771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 694771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 695771fe6b9SJerome Glisse union dig_transmitter_control args; 696771fe6b9SJerome Glisse int index = 0, num = 0; 697771fe6b9SJerome Glisse uint8_t frev, crev; 698771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 699771fe6b9SJerome Glisse struct drm_connector *connector; 700771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 701771fe6b9SJerome Glisse struct radeon_connector_atom_dig *dig_connector; 702771fe6b9SJerome Glisse 703771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 704771fe6b9SJerome Glisse if (!connector) 705771fe6b9SJerome Glisse return; 706771fe6b9SJerome Glisse 707771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 708771fe6b9SJerome Glisse 709771fe6b9SJerome Glisse if (!radeon_encoder->enc_priv) 710771fe6b9SJerome Glisse return; 711771fe6b9SJerome Glisse 712771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 713771fe6b9SJerome Glisse 714771fe6b9SJerome Glisse if (!radeon_connector->con_priv) 715771fe6b9SJerome Glisse return; 716771fe6b9SJerome Glisse 717771fe6b9SJerome Glisse dig_connector = radeon_connector->con_priv; 718771fe6b9SJerome Glisse 719771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 720771fe6b9SJerome Glisse 721771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) 722771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 723771fe6b9SJerome Glisse else { 724771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 725771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 726771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); 727771fe6b9SJerome Glisse break; 728771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 729771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); 730771fe6b9SJerome Glisse break; 731771fe6b9SJerome Glisse } 732771fe6b9SJerome Glisse } 733771fe6b9SJerome Glisse 734771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 735771fe6b9SJerome Glisse 736771fe6b9SJerome Glisse args.v1.ucAction = action; 737771fe6b9SJerome Glisse 738771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 739771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) { 740771fe6b9SJerome Glisse args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 2) / 100); 741771fe6b9SJerome Glisse args.v2.acConfig.fDualLinkConnector = 1; 742771fe6b9SJerome Glisse } else { 743771fe6b9SJerome Glisse args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 4) / 100); 744771fe6b9SJerome Glisse } 745771fe6b9SJerome Glisse if (dig->dig_block) 746771fe6b9SJerome Glisse args.v2.acConfig.ucEncoderSel = 1; 747771fe6b9SJerome Glisse 748771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 749771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 750771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 0; 751771fe6b9SJerome Glisse num = 0; 752771fe6b9SJerome Glisse break; 753771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 754771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 1; 755771fe6b9SJerome Glisse num = 1; 756771fe6b9SJerome Glisse break; 757771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 758771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 2; 759771fe6b9SJerome Glisse num = 2; 760771fe6b9SJerome Glisse break; 761771fe6b9SJerome Glisse } 762771fe6b9SJerome Glisse 763771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 764771fe6b9SJerome Glisse if (dig->coherent_mode) 765771fe6b9SJerome Glisse args.v2.acConfig.fCoherentMode = 1; 766771fe6b9SJerome Glisse } 767771fe6b9SJerome Glisse } else { 768771fe6b9SJerome Glisse args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 769771fe6b9SJerome Glisse args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock) / 10); 770771fe6b9SJerome Glisse 771771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 772771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 773771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 774771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) { 775771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) { 776771fe6b9SJerome Glisse args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 777771fe6b9SJerome Glisse ATOM_TRANSMITTER_CONFIG_LINKA_B); 778771fe6b9SJerome Glisse if (dig_connector->igp_lane_info & 0x3) 779771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 780771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0xc) 781771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 782771fe6b9SJerome Glisse } else { 783771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 784771fe6b9SJerome Glisse if (dig_connector->igp_lane_info & 0x1) 785771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 786771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x2) 787771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 788771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x4) 789771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 790771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x8) 791771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 792771fe6b9SJerome Glisse } 793771fe6b9SJerome Glisse } else { 794771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 795771fe6b9SJerome Glisse args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 796771fe6b9SJerome Glisse ATOM_TRANSMITTER_CONFIG_LINKA_B | 797771fe6b9SJerome Glisse ATOM_TRANSMITTER_CONFIG_LANE_0_7); 798771fe6b9SJerome Glisse else { 799771fe6b9SJerome Glisse if (dig_connector->linkb) 800771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 801771fe6b9SJerome Glisse else 802771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 803771fe6b9SJerome Glisse } 804771fe6b9SJerome Glisse } 805771fe6b9SJerome Glisse break; 806771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 807771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 808771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 809771fe6b9SJerome Glisse args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | 810771fe6b9SJerome Glisse ATOM_TRANSMITTER_CONFIG_LINKA_B | 811771fe6b9SJerome Glisse ATOM_TRANSMITTER_CONFIG_LANE_0_7); 812771fe6b9SJerome Glisse else { 813771fe6b9SJerome Glisse if (dig_connector->linkb) 814771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 815771fe6b9SJerome Glisse else 816771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; 817771fe6b9SJerome Glisse } 818771fe6b9SJerome Glisse break; 819771fe6b9SJerome Glisse } 820771fe6b9SJerome Glisse 821771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 822771fe6b9SJerome Glisse if (dig->coherent_mode) 823771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 824771fe6b9SJerome Glisse } 825771fe6b9SJerome Glisse } 826771fe6b9SJerome Glisse 827771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 828771fe6b9SJerome Glisse 829771fe6b9SJerome Glisse } 830771fe6b9SJerome Glisse 831771fe6b9SJerome Glisse static void 832771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable) 833771fe6b9SJerome Glisse { 834771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 835771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 836771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 837771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 838771fe6b9SJerome Glisse ENABLE_YUV_PS_ALLOCATION args; 839771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 840771fe6b9SJerome Glisse uint32_t temp, reg; 841771fe6b9SJerome Glisse 842771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 843771fe6b9SJerome Glisse 844771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 845771fe6b9SJerome Glisse reg = R600_BIOS_3_SCRATCH; 846771fe6b9SJerome Glisse else 847771fe6b9SJerome Glisse reg = RADEON_BIOS_3_SCRATCH; 848771fe6b9SJerome Glisse 849771fe6b9SJerome Glisse /* XXX: fix up scratch reg handling */ 850771fe6b9SJerome Glisse temp = RREG32(reg); 8514ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 852771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_TV1_ACTIVE | 853771fe6b9SJerome Glisse (radeon_crtc->crtc_id << 18))); 8544ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 855771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); 856771fe6b9SJerome Glisse else 857771fe6b9SJerome Glisse WREG32(reg, 0); 858771fe6b9SJerome Glisse 859771fe6b9SJerome Glisse if (enable) 860771fe6b9SJerome Glisse args.ucEnable = ATOM_ENABLE; 861771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 862771fe6b9SJerome Glisse 863771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 864771fe6b9SJerome Glisse 865771fe6b9SJerome Glisse WREG32(reg, temp); 866771fe6b9SJerome Glisse } 867771fe6b9SJerome Glisse 868771fe6b9SJerome Glisse static void 869771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) 870771fe6b9SJerome Glisse { 871771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 872771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 873771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 874771fe6b9SJerome Glisse DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 875771fe6b9SJerome Glisse int index = 0; 876771fe6b9SJerome Glisse bool is_dig = false; 8774ce001abSDave Airlie int devices; 878771fe6b9SJerome Glisse 879771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 880771fe6b9SJerome Glisse 8814ce001abSDave Airlie /* on DPMS off we have no idea if active device is meaningful */ 8824ce001abSDave Airlie if (mode != DRM_MODE_DPMS_ON && !radeon_encoder->active_device) 8834ce001abSDave Airlie devices = radeon_encoder->devices; 8844ce001abSDave Airlie else 8854ce001abSDave Airlie devices = radeon_encoder->active_device; 8864ce001abSDave Airlie 887f641e51eSDave Airlie DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 8884ce001abSDave Airlie radeon_encoder->encoder_id, mode, radeon_encoder->devices, 8894ce001abSDave Airlie radeon_encoder->active_device); 890771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 891771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 892771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 893771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 894771fe6b9SJerome Glisse break; 895771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 896771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 897771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 898771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 899771fe6b9SJerome Glisse is_dig = true; 900771fe6b9SJerome Glisse break; 901771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 902771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 903771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 904771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 905771fe6b9SJerome Glisse break; 906771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 907771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 908771fe6b9SJerome Glisse break; 909771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 910771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 911771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 912771fe6b9SJerome Glisse else 913771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 914771fe6b9SJerome Glisse break; 915771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 916771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 9174ce001abSDave Airlie if (devices & (ATOM_DEVICE_TV_SUPPORT)) 918771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 9194ce001abSDave Airlie else if (devices & (ATOM_DEVICE_CV_SUPPORT)) 920771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 921771fe6b9SJerome Glisse else 922771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 923771fe6b9SJerome Glisse break; 924771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 925771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 9264ce001abSDave Airlie if (devices & (ATOM_DEVICE_TV_SUPPORT)) 927771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 9284ce001abSDave Airlie else if (devices & (ATOM_DEVICE_CV_SUPPORT)) 929771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 930771fe6b9SJerome Glisse else 931771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 932771fe6b9SJerome Glisse break; 933771fe6b9SJerome Glisse } 934771fe6b9SJerome Glisse 935771fe6b9SJerome Glisse if (is_dig) { 936771fe6b9SJerome Glisse switch (mode) { 937771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 938771fe6b9SJerome Glisse atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE); 939771fe6b9SJerome Glisse break; 940771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 941771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 942771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 943771fe6b9SJerome Glisse atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE); 944771fe6b9SJerome Glisse break; 945771fe6b9SJerome Glisse } 946771fe6b9SJerome Glisse } else { 947771fe6b9SJerome Glisse switch (mode) { 948771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 949771fe6b9SJerome Glisse args.ucAction = ATOM_ENABLE; 950771fe6b9SJerome Glisse break; 951771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 952771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 953771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 954771fe6b9SJerome Glisse args.ucAction = ATOM_DISABLE; 955771fe6b9SJerome Glisse break; 956771fe6b9SJerome Glisse } 957771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 958771fe6b9SJerome Glisse } 959771fe6b9SJerome Glisse radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 960771fe6b9SJerome Glisse } 961771fe6b9SJerome Glisse 962771fe6b9SJerome Glisse union crtc_sourc_param { 963771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 964771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 965771fe6b9SJerome Glisse }; 966771fe6b9SJerome Glisse 967771fe6b9SJerome Glisse static void 968771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder) 969771fe6b9SJerome Glisse { 970771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 971771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 972771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 973771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 974771fe6b9SJerome Glisse union crtc_sourc_param args; 975771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 976771fe6b9SJerome Glisse uint8_t frev, crev; 977771fe6b9SJerome Glisse 978771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 979771fe6b9SJerome Glisse 980771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 981771fe6b9SJerome Glisse 982771fe6b9SJerome Glisse switch (frev) { 983771fe6b9SJerome Glisse case 1: 984771fe6b9SJerome Glisse switch (crev) { 985771fe6b9SJerome Glisse case 1: 986771fe6b9SJerome Glisse default: 987771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 988771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 989771fe6b9SJerome Glisse else { 990771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { 991771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 992771fe6b9SJerome Glisse } else { 993771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id << 2; 994771fe6b9SJerome Glisse } 995771fe6b9SJerome Glisse } 996771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 997771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 998771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 999771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1000771fe6b9SJerome Glisse break; 1001771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1002771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1003771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) 1004771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1005771fe6b9SJerome Glisse else 1006771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1007771fe6b9SJerome Glisse break; 1008771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1009771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1010771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1011771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1012771fe6b9SJerome Glisse break; 1013771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1014771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 10154ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1016771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 10174ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1018771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1019771fe6b9SJerome Glisse else 1020771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1021771fe6b9SJerome Glisse break; 1022771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1023771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 10244ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1025771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 10264ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1027771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1028771fe6b9SJerome Glisse else 1029771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1030771fe6b9SJerome Glisse break; 1031771fe6b9SJerome Glisse } 1032771fe6b9SJerome Glisse break; 1033771fe6b9SJerome Glisse case 2: 1034771fe6b9SJerome Glisse args.v2.ucCRTC = radeon_crtc->crtc_id; 1035771fe6b9SJerome Glisse args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1036771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1037771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1038771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1039771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1040771fe6b9SJerome Glisse if (ASIC_IS_DCE32(rdev)) { 1041771fe6b9SJerome Glisse if (radeon_crtc->crtc_id) 1042771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1043771fe6b9SJerome Glisse else 1044771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1045771fe6b9SJerome Glisse } else 1046771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1047771fe6b9SJerome Glisse break; 1048771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1049771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 1050771fe6b9SJerome Glisse break; 1051771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1052771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1053771fe6b9SJerome Glisse break; 1054771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 10554ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1056771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 10574ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1058771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1059771fe6b9SJerome Glisse else 1060771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1061771fe6b9SJerome Glisse break; 1062771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 10634ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1064771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 10654ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1066771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1067771fe6b9SJerome Glisse else 1068771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1069771fe6b9SJerome Glisse break; 1070771fe6b9SJerome Glisse } 1071771fe6b9SJerome Glisse break; 1072771fe6b9SJerome Glisse } 1073771fe6b9SJerome Glisse break; 1074771fe6b9SJerome Glisse default: 1075771fe6b9SJerome Glisse DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1076771fe6b9SJerome Glisse break; 1077771fe6b9SJerome Glisse } 1078771fe6b9SJerome Glisse 1079771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1080771fe6b9SJerome Glisse 1081771fe6b9SJerome Glisse } 1082771fe6b9SJerome Glisse 1083771fe6b9SJerome Glisse static void 1084771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder, 1085771fe6b9SJerome Glisse struct drm_display_mode *mode) 1086771fe6b9SJerome Glisse { 1087771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1088771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1089771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1090771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1091771fe6b9SJerome Glisse 1092771fe6b9SJerome Glisse /* Funky macbooks */ 1093771fe6b9SJerome Glisse if ((dev->pdev->device == 0x71C5) && 1094771fe6b9SJerome Glisse (dev->pdev->subsystem_vendor == 0x106b) && 1095771fe6b9SJerome Glisse (dev->pdev->subsystem_device == 0x0080)) { 1096771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1097771fe6b9SJerome Glisse uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1098771fe6b9SJerome Glisse 1099771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1100771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1101771fe6b9SJerome Glisse 1102771fe6b9SJerome Glisse WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1103771fe6b9SJerome Glisse } 1104771fe6b9SJerome Glisse } 1105771fe6b9SJerome Glisse 1106771fe6b9SJerome Glisse /* set scaler clears this on some chips */ 1107771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE)) 1108771fe6b9SJerome Glisse WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); 1109771fe6b9SJerome Glisse } 1110771fe6b9SJerome Glisse 1111771fe6b9SJerome Glisse static void 1112771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder, 1113771fe6b9SJerome Glisse struct drm_display_mode *mode, 1114771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 1115771fe6b9SJerome Glisse { 1116771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1117771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1118771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1119771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1120771fe6b9SJerome Glisse 1121771fe6b9SJerome Glisse if (radeon_encoder->enc_priv) { 1122771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig; 1123771fe6b9SJerome Glisse 1124771fe6b9SJerome Glisse dig = radeon_encoder->enc_priv; 1125771fe6b9SJerome Glisse dig->dig_block = radeon_crtc->crtc_id; 1126771fe6b9SJerome Glisse } 1127771fe6b9SJerome Glisse radeon_encoder->pixel_clock = adjusted_mode->clock; 1128771fe6b9SJerome Glisse 1129771fe6b9SJerome Glisse radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1130771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(encoder); 1131771fe6b9SJerome Glisse 1132771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) { 11334ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1134771fe6b9SJerome Glisse atombios_yuv_setup(encoder, true); 1135771fe6b9SJerome Glisse else 1136771fe6b9SJerome Glisse atombios_yuv_setup(encoder, false); 1137771fe6b9SJerome Glisse } 1138771fe6b9SJerome Glisse 1139771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1140771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1141771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1142771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1143771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1144771fe6b9SJerome Glisse atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 1145771fe6b9SJerome Glisse break; 1146771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1147771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1148771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1149771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1150771fe6b9SJerome Glisse /* disable the encoder and transmitter */ 1151771fe6b9SJerome Glisse atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE); 1152771fe6b9SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_DISABLE); 1153771fe6b9SJerome Glisse 1154771fe6b9SJerome Glisse /* setup and enable the encoder and transmitter */ 1155771fe6b9SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_ENABLE); 1156771fe6b9SJerome Glisse atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP); 1157771fe6b9SJerome Glisse atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE); 1158771fe6b9SJerome Glisse break; 1159771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1160771fe6b9SJerome Glisse atombios_ddia_setup(encoder, ATOM_ENABLE); 1161771fe6b9SJerome Glisse break; 1162771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1163771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1164771fe6b9SJerome Glisse atombios_external_tmds_setup(encoder, ATOM_ENABLE); 1165771fe6b9SJerome Glisse break; 1166771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1167771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1168771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1169771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1170771fe6b9SJerome Glisse atombios_dac_setup(encoder, ATOM_ENABLE); 11714ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1172771fe6b9SJerome Glisse atombios_tv_setup(encoder, ATOM_ENABLE); 1173771fe6b9SJerome Glisse break; 1174771fe6b9SJerome Glisse } 1175771fe6b9SJerome Glisse atombios_apply_encoder_quirks(encoder, adjusted_mode); 1176771fe6b9SJerome Glisse } 1177771fe6b9SJerome Glisse 1178771fe6b9SJerome Glisse static bool 11794ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1180771fe6b9SJerome Glisse { 1181771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1182771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1183771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 11844ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1185771fe6b9SJerome Glisse 1186771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | 1187771fe6b9SJerome Glisse ATOM_DEVICE_CV_SUPPORT | 1188771fe6b9SJerome Glisse ATOM_DEVICE_CRT_SUPPORT)) { 1189771fe6b9SJerome Glisse DAC_LOAD_DETECTION_PS_ALLOCATION args; 1190771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1191771fe6b9SJerome Glisse uint8_t frev, crev; 1192771fe6b9SJerome Glisse 1193771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1194771fe6b9SJerome Glisse 1195771fe6b9SJerome Glisse atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); 1196771fe6b9SJerome Glisse 1197771fe6b9SJerome Glisse args.sDacload.ucMisc = 0; 1198771fe6b9SJerome Glisse 1199771fe6b9SJerome Glisse if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1200771fe6b9SJerome Glisse (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) 1201771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_A; 1202771fe6b9SJerome Glisse else 1203771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_B; 1204771fe6b9SJerome Glisse 12054ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) 1206771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 12074ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) 1208771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 12094ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1210771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1211771fe6b9SJerome Glisse if (crev >= 3) 1212771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 12134ce001abSDave Airlie } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1214771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1215771fe6b9SJerome Glisse if (crev >= 3) 1216771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1217771fe6b9SJerome Glisse } 1218771fe6b9SJerome Glisse 1219771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1220771fe6b9SJerome Glisse 1221771fe6b9SJerome Glisse return true; 1222771fe6b9SJerome Glisse } else 1223771fe6b9SJerome Glisse return false; 1224771fe6b9SJerome Glisse } 1225771fe6b9SJerome Glisse 1226771fe6b9SJerome Glisse static enum drm_connector_status 1227771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1228771fe6b9SJerome Glisse { 1229771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1230771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1231771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 12324ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1233771fe6b9SJerome Glisse uint32_t bios_0_scratch; 1234771fe6b9SJerome Glisse 12354ce001abSDave Airlie if (!atombios_dac_load_detect(encoder, connector)) { 1236771fe6b9SJerome Glisse DRM_DEBUG("detect returned false \n"); 1237771fe6b9SJerome Glisse return connector_status_unknown; 1238771fe6b9SJerome Glisse } 1239771fe6b9SJerome Glisse 1240771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 1241771fe6b9SJerome Glisse bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 1242771fe6b9SJerome Glisse else 1243771fe6b9SJerome Glisse bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 1244771fe6b9SJerome Glisse 12454ce001abSDave Airlie DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 12464ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1247771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT1_MASK) 1248771fe6b9SJerome Glisse return connector_status_connected; 12494ce001abSDave Airlie } 12504ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1251771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT2_MASK) 1252771fe6b9SJerome Glisse return connector_status_connected; 12534ce001abSDave Airlie } 12544ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1255771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 1256771fe6b9SJerome Glisse return connector_status_connected; 12574ce001abSDave Airlie } 12584ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1259771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 1260771fe6b9SJerome Glisse return connector_status_connected; /* CTV */ 1261771fe6b9SJerome Glisse else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 1262771fe6b9SJerome Glisse return connector_status_connected; /* STV */ 1263771fe6b9SJerome Glisse } 1264771fe6b9SJerome Glisse return connector_status_disconnected; 1265771fe6b9SJerome Glisse } 1266771fe6b9SJerome Glisse 1267771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) 1268771fe6b9SJerome Glisse { 1269771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, true); 1270771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 12714ce001abSDave Airlie 12724ce001abSDave Airlie radeon_encoder_set_active_device(encoder); 1273771fe6b9SJerome Glisse } 1274771fe6b9SJerome Glisse 1275771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder) 1276771fe6b9SJerome Glisse { 1277771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 1278771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, false); 1279771fe6b9SJerome Glisse } 1280771fe6b9SJerome Glisse 12814ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder) 12824ce001abSDave Airlie { 12834ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 12844ce001abSDave Airlie radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 12854ce001abSDave Airlie radeon_encoder->active_device = 0; 12864ce001abSDave Airlie } 12874ce001abSDave Airlie 1288771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 1289771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 1290771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 1291771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 1292771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 1293771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 12944ce001abSDave Airlie .disable = radeon_atom_encoder_disable, 1295771fe6b9SJerome Glisse /* no detect for TMDS/LVDS yet */ 1296771fe6b9SJerome Glisse }; 1297771fe6b9SJerome Glisse 1298771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { 1299771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 1300771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 1301771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 1302771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 1303771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 1304771fe6b9SJerome Glisse .detect = radeon_atom_dac_detect, 1305771fe6b9SJerome Glisse }; 1306771fe6b9SJerome Glisse 1307771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder) 1308771fe6b9SJerome Glisse { 1309771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1310771fe6b9SJerome Glisse kfree(radeon_encoder->enc_priv); 1311771fe6b9SJerome Glisse drm_encoder_cleanup(encoder); 1312771fe6b9SJerome Glisse kfree(radeon_encoder); 1313771fe6b9SJerome Glisse } 1314771fe6b9SJerome Glisse 1315771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = { 1316771fe6b9SJerome Glisse .destroy = radeon_enc_destroy, 1317771fe6b9SJerome Glisse }; 1318771fe6b9SJerome Glisse 13194ce001abSDave Airlie struct radeon_encoder_atom_dac * 13204ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) 13214ce001abSDave Airlie { 13224ce001abSDave Airlie struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); 13234ce001abSDave Airlie 13244ce001abSDave Airlie if (!dac) 13254ce001abSDave Airlie return NULL; 13264ce001abSDave Airlie 13274ce001abSDave Airlie dac->tv_std = TV_STD_NTSC; 13284ce001abSDave Airlie return dac; 13294ce001abSDave Airlie } 13304ce001abSDave Airlie 1331771fe6b9SJerome Glisse struct radeon_encoder_atom_dig * 1332771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) 1333771fe6b9SJerome Glisse { 1334771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); 1335771fe6b9SJerome Glisse 1336771fe6b9SJerome Glisse if (!dig) 1337771fe6b9SJerome Glisse return NULL; 1338771fe6b9SJerome Glisse 1339771fe6b9SJerome Glisse /* coherent mode by default */ 1340771fe6b9SJerome Glisse dig->coherent_mode = true; 1341771fe6b9SJerome Glisse 1342771fe6b9SJerome Glisse return dig; 1343771fe6b9SJerome Glisse } 1344771fe6b9SJerome Glisse 1345771fe6b9SJerome Glisse void 1346771fe6b9SJerome Glisse radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) 1347771fe6b9SJerome Glisse { 1348*dfee5614SDave Airlie struct radeon_device *rdev = dev->dev_private; 1349771fe6b9SJerome Glisse struct drm_encoder *encoder; 1350771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 1351771fe6b9SJerome Glisse 1352771fe6b9SJerome Glisse /* see if we already added it */ 1353771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 1354771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 1355771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == encoder_id) { 1356771fe6b9SJerome Glisse radeon_encoder->devices |= supported_device; 1357771fe6b9SJerome Glisse return; 1358771fe6b9SJerome Glisse } 1359771fe6b9SJerome Glisse 1360771fe6b9SJerome Glisse } 1361771fe6b9SJerome Glisse 1362771fe6b9SJerome Glisse /* add a new one */ 1363771fe6b9SJerome Glisse radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); 1364771fe6b9SJerome Glisse if (!radeon_encoder) 1365771fe6b9SJerome Glisse return; 1366771fe6b9SJerome Glisse 1367771fe6b9SJerome Glisse encoder = &radeon_encoder->base; 1368*dfee5614SDave Airlie if (rdev->flags & RADEON_SINGLE_CRTC) 1369*dfee5614SDave Airlie encoder->possible_crtcs = 0x1; 1370*dfee5614SDave Airlie else 1371771fe6b9SJerome Glisse encoder->possible_crtcs = 0x3; 1372771fe6b9SJerome Glisse encoder->possible_clones = 0; 1373771fe6b9SJerome Glisse 1374771fe6b9SJerome Glisse radeon_encoder->enc_priv = NULL; 1375771fe6b9SJerome Glisse 1376771fe6b9SJerome Glisse radeon_encoder->encoder_id = encoder_id; 1377771fe6b9SJerome Glisse radeon_encoder->devices = supported_device; 1378c93bb85bSJerome Glisse radeon_encoder->rmx_type = RMX_OFF; 1379771fe6b9SJerome Glisse 1380771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1381771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1382771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1383771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1384771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1385771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1386771fe6b9SJerome Glisse radeon_encoder->rmx_type = RMX_FULL; 1387771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 1388771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 1389771fe6b9SJerome Glisse } else { 1390771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 1391771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 1392771fe6b9SJerome Glisse } 1393771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 1394771fe6b9SJerome Glisse break; 1395771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1396771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 1397771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 1398771fe6b9SJerome Glisse break; 1399771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1400771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1401771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1402771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); 14034ce001abSDave Airlie radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 1404771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 1405771fe6b9SJerome Glisse break; 1406771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1407771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1408771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1409771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1410771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1411771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1412771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 141360d15f55SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 141460d15f55SAlex Deucher radeon_encoder->rmx_type = RMX_FULL; 141560d15f55SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 141660d15f55SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 141760d15f55SAlex Deucher } else { 1418771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 1419771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 142060d15f55SAlex Deucher } 1421771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 1422771fe6b9SJerome Glisse break; 1423771fe6b9SJerome Glisse } 1424771fe6b9SJerome Glisse } 1425