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 345a9bcaccSAlex Deucher /* evil but including atombios.h is much worse */ 355a9bcaccSAlex Deucher bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, 365a9bcaccSAlex Deucher struct drm_display_mode *mode); 375a9bcaccSAlex Deucher 381f3b6a45SDave Airlie static uint32_t radeon_encoder_clones(struct drm_encoder *encoder) 391f3b6a45SDave Airlie { 401f3b6a45SDave Airlie struct drm_device *dev = encoder->dev; 411f3b6a45SDave Airlie struct radeon_device *rdev = dev->dev_private; 421f3b6a45SDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 431f3b6a45SDave Airlie struct drm_encoder *clone_encoder; 441f3b6a45SDave Airlie uint32_t index_mask = 0; 451f3b6a45SDave Airlie int count; 461f3b6a45SDave Airlie 471f3b6a45SDave Airlie /* DIG routing gets problematic */ 481f3b6a45SDave Airlie if (rdev->family >= CHIP_R600) 491f3b6a45SDave Airlie return index_mask; 501f3b6a45SDave Airlie /* LVDS/TV are too wacky */ 511f3b6a45SDave Airlie if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) 521f3b6a45SDave Airlie return index_mask; 531f3b6a45SDave Airlie /* DVO requires 2x ppll clocks depending on tmds chip */ 541f3b6a45SDave Airlie if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) 551f3b6a45SDave Airlie return index_mask; 561f3b6a45SDave Airlie 571f3b6a45SDave Airlie count = -1; 581f3b6a45SDave Airlie list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) { 591f3b6a45SDave Airlie struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder); 601f3b6a45SDave Airlie count++; 611f3b6a45SDave Airlie 621f3b6a45SDave Airlie if (clone_encoder == encoder) 631f3b6a45SDave Airlie continue; 641f3b6a45SDave Airlie if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT)) 651f3b6a45SDave Airlie continue; 661f3b6a45SDave Airlie if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT) 671f3b6a45SDave Airlie continue; 681f3b6a45SDave Airlie else 691f3b6a45SDave Airlie index_mask |= (1 << count); 701f3b6a45SDave Airlie } 711f3b6a45SDave Airlie return index_mask; 721f3b6a45SDave Airlie } 731f3b6a45SDave Airlie 741f3b6a45SDave Airlie void radeon_setup_encoder_clones(struct drm_device *dev) 751f3b6a45SDave Airlie { 761f3b6a45SDave Airlie struct drm_encoder *encoder; 771f3b6a45SDave Airlie 781f3b6a45SDave Airlie list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 791f3b6a45SDave Airlie encoder->possible_clones = radeon_encoder_clones(encoder); 801f3b6a45SDave Airlie } 811f3b6a45SDave Airlie } 821f3b6a45SDave Airlie 83771fe6b9SJerome Glisse uint32_t 845137ee94SAlex Deucher radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac) 85771fe6b9SJerome Glisse { 86771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 87771fe6b9SJerome Glisse uint32_t ret = 0; 88771fe6b9SJerome Glisse 89771fe6b9SJerome Glisse switch (supported_device) { 90771fe6b9SJerome Glisse case ATOM_DEVICE_CRT1_SUPPORT: 91771fe6b9SJerome Glisse case ATOM_DEVICE_TV1_SUPPORT: 92771fe6b9SJerome Glisse case ATOM_DEVICE_TV2_SUPPORT: 93771fe6b9SJerome Glisse case ATOM_DEVICE_CRT2_SUPPORT: 94771fe6b9SJerome Glisse case ATOM_DEVICE_CV_SUPPORT: 95771fe6b9SJerome Glisse switch (dac) { 96771fe6b9SJerome Glisse case 1: /* dac a */ 97771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS300) || 98771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 99771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) 1005137ee94SAlex Deucher ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 101771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 1025137ee94SAlex Deucher ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 103771fe6b9SJerome Glisse else 1045137ee94SAlex Deucher ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 105771fe6b9SJerome Glisse break; 106771fe6b9SJerome Glisse case 2: /* dac b */ 107771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 1085137ee94SAlex Deucher ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 109771fe6b9SJerome Glisse else { 110771fe6b9SJerome Glisse /*if (rdev->family == CHIP_R200) 1115137ee94SAlex Deucher ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 112771fe6b9SJerome Glisse else*/ 1135137ee94SAlex Deucher ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 114771fe6b9SJerome Glisse } 115771fe6b9SJerome Glisse break; 116771fe6b9SJerome Glisse case 3: /* external dac */ 117771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 1185137ee94SAlex Deucher ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 119771fe6b9SJerome Glisse else 1205137ee94SAlex Deucher ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 121771fe6b9SJerome Glisse break; 122771fe6b9SJerome Glisse } 123771fe6b9SJerome Glisse break; 124771fe6b9SJerome Glisse case ATOM_DEVICE_LCD1_SUPPORT: 125771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 1265137ee94SAlex Deucher ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 127771fe6b9SJerome Glisse else 1285137ee94SAlex Deucher ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 129771fe6b9SJerome Glisse break; 130771fe6b9SJerome Glisse case ATOM_DEVICE_DFP1_SUPPORT: 131771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS300) || 132771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 133771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) 1345137ee94SAlex Deucher ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 135771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 1365137ee94SAlex Deucher ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 137771fe6b9SJerome Glisse else 1385137ee94SAlex Deucher ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 139771fe6b9SJerome Glisse break; 140771fe6b9SJerome Glisse case ATOM_DEVICE_LCD2_SUPPORT: 141771fe6b9SJerome Glisse case ATOM_DEVICE_DFP2_SUPPORT: 142771fe6b9SJerome Glisse if ((rdev->family == CHIP_RS600) || 143771fe6b9SJerome Glisse (rdev->family == CHIP_RS690) || 144771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) 1455137ee94SAlex Deucher ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 146771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 1475137ee94SAlex Deucher ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 148771fe6b9SJerome Glisse else 1495137ee94SAlex Deucher ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 150771fe6b9SJerome Glisse break; 151771fe6b9SJerome Glisse case ATOM_DEVICE_DFP3_SUPPORT: 1525137ee94SAlex Deucher ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 153771fe6b9SJerome Glisse break; 154771fe6b9SJerome Glisse } 155771fe6b9SJerome Glisse 156771fe6b9SJerome Glisse return ret; 157771fe6b9SJerome Glisse } 158771fe6b9SJerome Glisse 159f28cf339SDave Airlie static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) 160f28cf339SDave Airlie { 161f28cf339SDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 162f28cf339SDave Airlie switch (radeon_encoder->encoder_id) { 163f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_LVDS: 164f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 165f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 166f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 167f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_DVO1: 168f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 169f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_DDI: 170f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 171f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 172f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 173f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 174f28cf339SDave Airlie return true; 175f28cf339SDave Airlie default: 176f28cf339SDave Airlie return false; 177f28cf339SDave Airlie } 178f28cf339SDave Airlie } 17999999aaaSAlex Deucher 180771fe6b9SJerome Glisse void 181771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev) 182771fe6b9SJerome Glisse { 183771fe6b9SJerome Glisse struct drm_connector *connector; 184771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 185771fe6b9SJerome Glisse struct drm_encoder *encoder; 186771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 187771fe6b9SJerome Glisse 188771fe6b9SJerome Glisse /* walk the list and link encoders to connectors */ 189771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 190771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 191771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 192771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 193771fe6b9SJerome Glisse if (radeon_encoder->devices & radeon_connector->devices) 194771fe6b9SJerome Glisse drm_mode_connector_attach_encoder(connector, encoder); 195771fe6b9SJerome Glisse } 196771fe6b9SJerome Glisse } 197771fe6b9SJerome Glisse } 198771fe6b9SJerome Glisse 1994ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder) 2004ce001abSDave Airlie { 2014ce001abSDave Airlie struct drm_device *dev = encoder->dev; 2024ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2034ce001abSDave Airlie struct drm_connector *connector; 2044ce001abSDave Airlie 2054ce001abSDave Airlie list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2064ce001abSDave Airlie if (connector->encoder == encoder) { 2074ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2084ce001abSDave Airlie radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; 209d9fdaafbSDave Airlie DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n", 2104ce001abSDave Airlie radeon_encoder->active_device, radeon_encoder->devices, 2114ce001abSDave Airlie radeon_connector->devices, encoder->encoder_type); 2124ce001abSDave Airlie } 2134ce001abSDave Airlie } 2144ce001abSDave Airlie } 2154ce001abSDave Airlie 2165b1714d3SAlex Deucher struct drm_connector * 217771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder) 218771fe6b9SJerome Glisse { 219771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 220771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 221771fe6b9SJerome Glisse struct drm_connector *connector; 222771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 223771fe6b9SJerome Glisse 224771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 225771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 22643c33ed8SDave Airlie if (radeon_encoder->active_device & radeon_connector->devices) 227771fe6b9SJerome Glisse return connector; 228771fe6b9SJerome Glisse } 229771fe6b9SJerome Glisse return NULL; 230771fe6b9SJerome Glisse } 231771fe6b9SJerome Glisse 232ac89af1eSAlex Deucher static struct drm_connector * 233ac89af1eSAlex Deucher radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) 234ac89af1eSAlex Deucher { 235ac89af1eSAlex Deucher struct drm_device *dev = encoder->dev; 236ac89af1eSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 237ac89af1eSAlex Deucher struct drm_connector *connector; 238ac89af1eSAlex Deucher struct radeon_connector *radeon_connector; 239ac89af1eSAlex Deucher 240ac89af1eSAlex Deucher list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 241ac89af1eSAlex Deucher radeon_connector = to_radeon_connector(connector); 242ac89af1eSAlex Deucher if (radeon_encoder->devices & radeon_connector->devices) 243ac89af1eSAlex Deucher return connector; 244ac89af1eSAlex Deucher } 245ac89af1eSAlex Deucher return NULL; 246ac89af1eSAlex Deucher } 247ac89af1eSAlex Deucher 2483e4b9982SAlex Deucher struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder) 2493e4b9982SAlex Deucher { 2503e4b9982SAlex Deucher struct drm_device *dev = encoder->dev; 2513e4b9982SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2523e4b9982SAlex Deucher struct drm_encoder *other_encoder; 2533e4b9982SAlex Deucher struct radeon_encoder *other_radeon_encoder; 2543e4b9982SAlex Deucher 2553e4b9982SAlex Deucher if (radeon_encoder->is_ext_encoder) 2563e4b9982SAlex Deucher return NULL; 2573e4b9982SAlex Deucher 2583e4b9982SAlex Deucher list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { 2593e4b9982SAlex Deucher if (other_encoder == encoder) 2603e4b9982SAlex Deucher continue; 2613e4b9982SAlex Deucher other_radeon_encoder = to_radeon_encoder(other_encoder); 2623e4b9982SAlex Deucher if (other_radeon_encoder->is_ext_encoder && 2633e4b9982SAlex Deucher (radeon_encoder->devices & other_radeon_encoder->devices)) 2643e4b9982SAlex Deucher return other_encoder; 2653e4b9982SAlex Deucher } 2663e4b9982SAlex Deucher return NULL; 2673e4b9982SAlex Deucher } 2683e4b9982SAlex Deucher 269*1d33e1fcSAlex Deucher u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder) 270d7fa8bb3SAlex Deucher { 271d7fa8bb3SAlex Deucher struct drm_encoder *other_encoder = radeon_atom_get_external_encoder(encoder); 272d7fa8bb3SAlex Deucher 273d7fa8bb3SAlex Deucher if (other_encoder) { 274d7fa8bb3SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(other_encoder); 275d7fa8bb3SAlex Deucher 276d7fa8bb3SAlex Deucher switch (radeon_encoder->encoder_id) { 277d7fa8bb3SAlex Deucher case ENCODER_OBJECT_ID_TRAVIS: 278d7fa8bb3SAlex Deucher case ENCODER_OBJECT_ID_NUTMEG: 279d7fa8bb3SAlex Deucher return true; 280d7fa8bb3SAlex Deucher default: 281d7fa8bb3SAlex Deucher return false; 282d7fa8bb3SAlex Deucher } 283d7fa8bb3SAlex Deucher } 284d7fa8bb3SAlex Deucher 285d7fa8bb3SAlex Deucher return false; 286d7fa8bb3SAlex Deucher } 287d7fa8bb3SAlex Deucher 2883515387bSAlex Deucher void radeon_panel_mode_fixup(struct drm_encoder *encoder, 2893515387bSAlex Deucher struct drm_display_mode *adjusted_mode) 2903515387bSAlex Deucher { 2913515387bSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2923515387bSAlex Deucher struct drm_device *dev = encoder->dev; 2933515387bSAlex Deucher struct radeon_device *rdev = dev->dev_private; 2943515387bSAlex Deucher struct drm_display_mode *native_mode = &radeon_encoder->native_mode; 2953515387bSAlex Deucher unsigned hblank = native_mode->htotal - native_mode->hdisplay; 2963515387bSAlex Deucher unsigned vblank = native_mode->vtotal - native_mode->vdisplay; 2973515387bSAlex Deucher unsigned hover = native_mode->hsync_start - native_mode->hdisplay; 2983515387bSAlex Deucher unsigned vover = native_mode->vsync_start - native_mode->vdisplay; 2993515387bSAlex Deucher unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start; 3003515387bSAlex Deucher unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start; 3013515387bSAlex Deucher 3023515387bSAlex Deucher adjusted_mode->clock = native_mode->clock; 3033515387bSAlex Deucher adjusted_mode->flags = native_mode->flags; 3043515387bSAlex Deucher 3053515387bSAlex Deucher if (ASIC_IS_AVIVO(rdev)) { 3063515387bSAlex Deucher adjusted_mode->hdisplay = native_mode->hdisplay; 3073515387bSAlex Deucher adjusted_mode->vdisplay = native_mode->vdisplay; 3083515387bSAlex Deucher } 3093515387bSAlex Deucher 3103515387bSAlex Deucher adjusted_mode->htotal = native_mode->hdisplay + hblank; 3113515387bSAlex Deucher adjusted_mode->hsync_start = native_mode->hdisplay + hover; 3123515387bSAlex Deucher adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width; 3133515387bSAlex Deucher 3143515387bSAlex Deucher adjusted_mode->vtotal = native_mode->vdisplay + vblank; 3153515387bSAlex Deucher adjusted_mode->vsync_start = native_mode->vdisplay + vover; 3163515387bSAlex Deucher adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width; 3173515387bSAlex Deucher 3183515387bSAlex Deucher drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 3193515387bSAlex Deucher 3203515387bSAlex Deucher if (ASIC_IS_AVIVO(rdev)) { 3213515387bSAlex Deucher adjusted_mode->crtc_hdisplay = native_mode->hdisplay; 3223515387bSAlex Deucher adjusted_mode->crtc_vdisplay = native_mode->vdisplay; 3233515387bSAlex Deucher } 3243515387bSAlex Deucher 3253515387bSAlex Deucher adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank; 3263515387bSAlex Deucher adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover; 3273515387bSAlex Deucher adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width; 3283515387bSAlex Deucher 3293515387bSAlex Deucher adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank; 3303515387bSAlex Deucher adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover; 3313515387bSAlex Deucher adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width; 3323515387bSAlex Deucher 3333515387bSAlex Deucher } 3343515387bSAlex Deucher 335771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, 336771fe6b9SJerome Glisse struct drm_display_mode *mode, 337771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 338771fe6b9SJerome Glisse { 339771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 3405a9bcaccSAlex Deucher struct drm_device *dev = encoder->dev; 3415a9bcaccSAlex Deucher struct radeon_device *rdev = dev->dev_private; 342771fe6b9SJerome Glisse 3438c2a6d73SAlex Deucher /* set the active encoder to connector routing */ 3448c2a6d73SAlex Deucher radeon_encoder_set_active_device(encoder); 345771fe6b9SJerome Glisse drm_mode_set_crtcinfo(adjusted_mode, 0); 346771fe6b9SJerome Glisse 347771fe6b9SJerome Glisse /* hw bug */ 348771fe6b9SJerome Glisse if ((mode->flags & DRM_MODE_FLAG_INTERLACE) 349771fe6b9SJerome Glisse && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) 350771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; 351771fe6b9SJerome Glisse 35280297e87SAlex Deucher /* get the native mode for LVDS */ 3533515387bSAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 3543515387bSAlex Deucher radeon_panel_mode_fixup(encoder, adjusted_mode); 35580297e87SAlex Deucher 35680297e87SAlex Deucher /* get the native mode for TV */ 357ceefedd8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 3585a9bcaccSAlex Deucher struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; 3595a9bcaccSAlex Deucher if (tv_dac) { 3605a9bcaccSAlex Deucher if (tv_dac->tv_std == TV_STD_NTSC || 3615a9bcaccSAlex Deucher tv_dac->tv_std == TV_STD_NTSC_J || 3625a9bcaccSAlex Deucher tv_dac->tv_std == TV_STD_PAL_M) 3635a9bcaccSAlex Deucher radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); 3645a9bcaccSAlex Deucher else 3655a9bcaccSAlex Deucher radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); 3665a9bcaccSAlex Deucher } 3675a9bcaccSAlex Deucher } 3685a9bcaccSAlex Deucher 3695801ead6SAlex Deucher if (ASIC_IS_DCE3(rdev) && 37011b0a5b8SAlex Deucher ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || 371*1d33e1fcSAlex Deucher (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { 3725801ead6SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 3735801ead6SAlex Deucher radeon_dp_set_link_config(connector, mode); 3745801ead6SAlex Deucher } 3755801ead6SAlex Deucher 376771fe6b9SJerome Glisse return true; 377771fe6b9SJerome Glisse } 378771fe6b9SJerome Glisse 379771fe6b9SJerome Glisse static void 380771fe6b9SJerome Glisse atombios_dac_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 DAC_ENCODER_CONTROL_PS_ALLOCATION args; 386affd8589SAlex Deucher int index = 0; 387445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 388445282dbSDave Airlie 389771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 390771fe6b9SJerome Glisse 391771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 392771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 393771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 394771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 395771fe6b9SJerome Glisse break; 396771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 397771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 398771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 399771fe6b9SJerome Glisse break; 400771fe6b9SJerome Glisse } 401771fe6b9SJerome Glisse 402771fe6b9SJerome Glisse args.ucAction = action; 403771fe6b9SJerome Glisse 4044ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 405771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PS2; 4064ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 407771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_CV; 408771fe6b9SJerome Glisse else { 409affd8589SAlex Deucher switch (dac_info->tv_std) { 410771fe6b9SJerome Glisse case TV_STD_PAL: 411771fe6b9SJerome Glisse case TV_STD_PAL_M: 412771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 413771fe6b9SJerome Glisse case TV_STD_SECAM: 414771fe6b9SJerome Glisse case TV_STD_PAL_CN: 415771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PAL; 416771fe6b9SJerome Glisse break; 417771fe6b9SJerome Glisse case TV_STD_NTSC: 418771fe6b9SJerome Glisse case TV_STD_NTSC_J: 419771fe6b9SJerome Glisse case TV_STD_PAL_60: 420771fe6b9SJerome Glisse default: 421771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_NTSC; 422771fe6b9SJerome Glisse break; 423771fe6b9SJerome Glisse } 424771fe6b9SJerome Glisse } 425771fe6b9SJerome Glisse args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 426771fe6b9SJerome Glisse 427771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 428771fe6b9SJerome Glisse 429771fe6b9SJerome Glisse } 430771fe6b9SJerome Glisse 431771fe6b9SJerome Glisse static void 432771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action) 433771fe6b9SJerome Glisse { 434771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 435771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 436771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 437771fe6b9SJerome Glisse TV_ENCODER_CONTROL_PS_ALLOCATION args; 438771fe6b9SJerome Glisse int index = 0; 439445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 440445282dbSDave Airlie 441771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 442771fe6b9SJerome Glisse 443771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 444771fe6b9SJerome Glisse 445771fe6b9SJerome Glisse args.sTVEncoder.ucAction = action; 446771fe6b9SJerome Glisse 4474ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 448771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 449771fe6b9SJerome Glisse else { 450affd8589SAlex Deucher switch (dac_info->tv_std) { 451771fe6b9SJerome Glisse case TV_STD_NTSC: 452771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 453771fe6b9SJerome Glisse break; 454771fe6b9SJerome Glisse case TV_STD_PAL: 455771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 456771fe6b9SJerome Glisse break; 457771fe6b9SJerome Glisse case TV_STD_PAL_M: 458771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 459771fe6b9SJerome Glisse break; 460771fe6b9SJerome Glisse case TV_STD_PAL_60: 461771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 462771fe6b9SJerome Glisse break; 463771fe6b9SJerome Glisse case TV_STD_NTSC_J: 464771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 465771fe6b9SJerome Glisse break; 466771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 467771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 468771fe6b9SJerome Glisse break; 469771fe6b9SJerome Glisse case TV_STD_SECAM: 470771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 471771fe6b9SJerome Glisse break; 472771fe6b9SJerome Glisse case TV_STD_PAL_CN: 473771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 474771fe6b9SJerome Glisse break; 475771fe6b9SJerome Glisse default: 476771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 477771fe6b9SJerome Glisse break; 478771fe6b9SJerome Glisse } 479771fe6b9SJerome Glisse } 480771fe6b9SJerome Glisse 481771fe6b9SJerome Glisse args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 482771fe6b9SJerome Glisse 483771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 484771fe6b9SJerome Glisse 485771fe6b9SJerome Glisse } 486771fe6b9SJerome Glisse 48799999aaaSAlex Deucher union dvo_encoder_control { 48899999aaaSAlex Deucher ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds; 48999999aaaSAlex Deucher DVO_ENCODER_CONTROL_PS_ALLOCATION dvo; 49099999aaaSAlex Deucher DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3; 49199999aaaSAlex Deucher }; 49299999aaaSAlex Deucher 493771fe6b9SJerome Glisse void 49499999aaaSAlex Deucher atombios_dvo_setup(struct drm_encoder *encoder, int action) 495771fe6b9SJerome Glisse { 496771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 497771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 498771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 49999999aaaSAlex Deucher union dvo_encoder_control args; 50099999aaaSAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 501771fe6b9SJerome Glisse 502771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 503771fe6b9SJerome Glisse 50499999aaaSAlex Deucher if (ASIC_IS_DCE3(rdev)) { 50599999aaaSAlex Deucher /* DCE3+ */ 50699999aaaSAlex Deucher args.dvo_v3.ucAction = action; 50799999aaaSAlex Deucher args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 50899999aaaSAlex Deucher args.dvo_v3.ucDVOConfig = 0; /* XXX */ 50999999aaaSAlex Deucher } else if (ASIC_IS_DCE2(rdev)) { 51099999aaaSAlex Deucher /* DCE2 (pre-DCE3 R6xx, RS600/690/740 */ 51199999aaaSAlex Deucher args.dvo.sDVOEncoder.ucAction = action; 51299999aaaSAlex Deucher args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 51399999aaaSAlex Deucher /* DFP1, CRT1, TV1 depending on the type of port */ 51499999aaaSAlex Deucher args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; 515771fe6b9SJerome Glisse 516771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 51799999aaaSAlex Deucher args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; 51899999aaaSAlex Deucher } else { 51999999aaaSAlex Deucher /* R4xx, R5xx */ 52099999aaaSAlex Deucher args.ext_tmds.sXTmdsEncoder.ucEnable = action; 52199999aaaSAlex Deucher 52299999aaaSAlex Deucher if (radeon_encoder->pixel_clock > 165000) 52399999aaaSAlex Deucher args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; 524771fe6b9SJerome Glisse 525771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8)*/ 52699999aaaSAlex Deucher args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; 527771fe6b9SJerome Glisse } 528771fe6b9SJerome Glisse 529771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 530771fe6b9SJerome Glisse } 531771fe6b9SJerome Glisse 532771fe6b9SJerome Glisse union lvds_encoder_control { 533771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 534771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 535771fe6b9SJerome Glisse }; 536771fe6b9SJerome Glisse 53732f48ffeSAlex Deucher void 538771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action) 539771fe6b9SJerome Glisse { 540771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 541771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 542771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 5439ae47867SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 544771fe6b9SJerome Glisse union lvds_encoder_control args; 545771fe6b9SJerome Glisse int index = 0; 546dafc3bd5SChristian Koenig int hdmi_detected = 0; 547771fe6b9SJerome Glisse uint8_t frev, crev; 548771fe6b9SJerome Glisse 5494aab97e8SAlex Deucher if (!dig) 550771fe6b9SJerome Glisse return; 551771fe6b9SJerome Glisse 5529ae47867SAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 553dafc3bd5SChristian Koenig hdmi_detected = 1; 554dafc3bd5SChristian Koenig 555771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 556771fe6b9SJerome Glisse 557771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 558771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 559771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 560771fe6b9SJerome Glisse break; 561771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 562771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 563771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 564771fe6b9SJerome Glisse break; 565771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 566771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 567771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 568771fe6b9SJerome Glisse else 569771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 570771fe6b9SJerome Glisse break; 571771fe6b9SJerome Glisse } 572771fe6b9SJerome Glisse 573a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 574a084e6eeSAlex Deucher return; 575771fe6b9SJerome Glisse 576771fe6b9SJerome Glisse switch (frev) { 577771fe6b9SJerome Glisse case 1: 578771fe6b9SJerome Glisse case 2: 579771fe6b9SJerome Glisse switch (crev) { 580771fe6b9SJerome Glisse case 1: 581771fe6b9SJerome Glisse args.v1.ucMisc = 0; 582771fe6b9SJerome Glisse args.v1.ucAction = action; 583dafc3bd5SChristian Koenig if (hdmi_detected) 584771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 585771fe6b9SJerome Glisse args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 586771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 587ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 588771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 589ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 59099999aaaSAlex Deucher args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 591771fe6b9SJerome Glisse } else { 5925137ee94SAlex Deucher if (dig->linkb) 593771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 594771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 595771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 596771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8) */ 59799999aaaSAlex Deucher args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 598771fe6b9SJerome Glisse } 599771fe6b9SJerome Glisse break; 600771fe6b9SJerome Glisse case 2: 601771fe6b9SJerome Glisse case 3: 602771fe6b9SJerome Glisse args.v2.ucMisc = 0; 603771fe6b9SJerome Glisse args.v2.ucAction = action; 604771fe6b9SJerome Glisse if (crev == 3) { 605771fe6b9SJerome Glisse if (dig->coherent_mode) 606771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 607771fe6b9SJerome Glisse } 608dafc3bd5SChristian Koenig if (hdmi_detected) 609771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 610771fe6b9SJerome Glisse args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 611771fe6b9SJerome Glisse args.v2.ucTruncate = 0; 612771fe6b9SJerome Glisse args.v2.ucSpatial = 0; 613771fe6b9SJerome Glisse args.v2.ucTemporal = 0; 614771fe6b9SJerome Glisse args.v2.ucFRC = 0; 615771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 616ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 617771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 618ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { 619771fe6b9SJerome Glisse args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 620ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 621771fe6b9SJerome Glisse args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 622771fe6b9SJerome Glisse } 623ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { 624771fe6b9SJerome Glisse args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 625ba032a58SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 626771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 627ba032a58SAlex Deucher if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) 628771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 629771fe6b9SJerome Glisse } 630771fe6b9SJerome Glisse } else { 6315137ee94SAlex Deucher if (dig->linkb) 632771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 633771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 634771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 635771fe6b9SJerome Glisse } 636771fe6b9SJerome Glisse break; 637771fe6b9SJerome Glisse default: 638771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 639771fe6b9SJerome Glisse break; 640771fe6b9SJerome Glisse } 641771fe6b9SJerome Glisse break; 642771fe6b9SJerome Glisse default: 643771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 644771fe6b9SJerome Glisse break; 645771fe6b9SJerome Glisse } 646771fe6b9SJerome Glisse 647771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 648771fe6b9SJerome Glisse } 649771fe6b9SJerome Glisse 650771fe6b9SJerome Glisse int 651771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder) 652771fe6b9SJerome Glisse { 653c7a71fc7SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 654d033af87SAlex Deucher struct drm_device *dev = encoder->dev; 655d033af87SAlex Deucher struct radeon_device *rdev = dev->dev_private; 656771fe6b9SJerome Glisse struct drm_connector *connector; 657771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 6589ae47867SAlex Deucher struct radeon_connector_atom_dig *dig_connector; 659771fe6b9SJerome Glisse 660d7fa8bb3SAlex Deucher /* dp bridges are always DP */ 661*1d33e1fcSAlex Deucher if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) 662d7fa8bb3SAlex Deucher return ATOM_ENCODER_MODE_DP; 663d7fa8bb3SAlex Deucher 664fbb87773SAlex Deucher /* DVO is always DVO */ 665fbb87773SAlex Deucher if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO) 666fbb87773SAlex Deucher return ATOM_ENCODER_MODE_DVO; 667fbb87773SAlex Deucher 668771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 669fbb87773SAlex Deucher /* if we don't have an active device yet, just use one of 670fbb87773SAlex Deucher * the connectors tied to the encoder. 671fbb87773SAlex Deucher */ 672fbb87773SAlex Deucher if (!connector) 673fbb87773SAlex Deucher connector = radeon_get_connector_for_encoder_init(encoder); 674771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 675771fe6b9SJerome Glisse 676771fe6b9SJerome Glisse switch (connector->connector_type) { 677771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVII: 678705af9c7SAlex Deucher case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ 6799453d621SAlex Deucher if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { 680d033af87SAlex Deucher /* fix me */ 681d033af87SAlex Deucher if (ASIC_IS_DCE4(rdev)) 682d033af87SAlex Deucher return ATOM_ENCODER_MODE_DVI; 683d033af87SAlex Deucher else 684771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 685d033af87SAlex Deucher } else if (radeon_connector->use_digital) 686771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 687771fe6b9SJerome Glisse else 688771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 689771fe6b9SJerome Glisse break; 690771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVID: 691771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_HDMIA: 692771fe6b9SJerome Glisse default: 6939453d621SAlex Deucher if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { 694d033af87SAlex Deucher /* fix me */ 695d033af87SAlex Deucher if (ASIC_IS_DCE4(rdev)) 696d033af87SAlex Deucher return ATOM_ENCODER_MODE_DVI; 697771fe6b9SJerome Glisse else 698d033af87SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 699d033af87SAlex Deucher } else 700771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 701771fe6b9SJerome Glisse break; 702771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_LVDS: 703771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_LVDS; 704771fe6b9SJerome Glisse break; 705771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DisplayPort: 7069ae47867SAlex Deucher dig_connector = radeon_connector->con_priv; 7079ae47867SAlex Deucher if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 7089ae47867SAlex Deucher (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) 709771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DP; 7109453d621SAlex Deucher else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { 711d033af87SAlex Deucher /* fix me */ 712d033af87SAlex Deucher if (ASIC_IS_DCE4(rdev)) 713d033af87SAlex Deucher return ATOM_ENCODER_MODE_DVI; 714771fe6b9SJerome Glisse else 715d033af87SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 716d033af87SAlex Deucher } else 717771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 718771fe6b9SJerome Glisse break; 7193a5f4a21SAlex Deucher case DRM_MODE_CONNECTOR_eDP: 7203a5f4a21SAlex Deucher return ATOM_ENCODER_MODE_DP; 721a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_DVIA: 722a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_VGA: 723771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 724771fe6b9SJerome Glisse break; 725a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_Composite: 726a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_SVIDEO: 727a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_9PinDIN: 728771fe6b9SJerome Glisse /* fix me */ 729771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_TV; 730771fe6b9SJerome Glisse /*return ATOM_ENCODER_MODE_CV;*/ 731771fe6b9SJerome Glisse break; 732771fe6b9SJerome Glisse } 733771fe6b9SJerome Glisse } 734771fe6b9SJerome Glisse 7351a66c95aSAlex Deucher /* 7361a66c95aSAlex Deucher * DIG Encoder/Transmitter Setup 7371a66c95aSAlex Deucher * 7381a66c95aSAlex Deucher * DCE 3.0/3.1 7391a66c95aSAlex Deucher * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. 7401a66c95aSAlex Deucher * Supports up to 3 digital outputs 7411a66c95aSAlex Deucher * - 2 DIG encoder blocks. 7421a66c95aSAlex Deucher * DIG1 can drive UNIPHY link A or link B 7431a66c95aSAlex Deucher * DIG2 can drive UNIPHY link B or LVTMA 7441a66c95aSAlex Deucher * 7451a66c95aSAlex Deucher * DCE 3.2 7461a66c95aSAlex Deucher * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). 7471a66c95aSAlex Deucher * Supports up to 5 digital outputs 7481a66c95aSAlex Deucher * - 2 DIG encoder blocks. 7491a66c95aSAlex Deucher * DIG1/2 can drive UNIPHY0/1/2 link A or link B 7501a66c95aSAlex Deucher * 751a001182aSAlex Deucher * DCE 4.0/5.0 7524e8c65a1SAlex Deucher * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). 753bcc1c2a1SAlex Deucher * Supports up to 6 digital outputs 754bcc1c2a1SAlex Deucher * - 6 DIG encoder blocks. 755bcc1c2a1SAlex Deucher * - DIG to PHY mapping is hardcoded 756bcc1c2a1SAlex Deucher * DIG1 drives UNIPHY0 link A, A+B 757bcc1c2a1SAlex Deucher * DIG2 drives UNIPHY0 link B 758bcc1c2a1SAlex Deucher * DIG3 drives UNIPHY1 link A, A+B 759bcc1c2a1SAlex Deucher * DIG4 drives UNIPHY1 link B 760bcc1c2a1SAlex Deucher * DIG5 drives UNIPHY2 link A, A+B 761bcc1c2a1SAlex Deucher * DIG6 drives UNIPHY2 link B 762bcc1c2a1SAlex Deucher * 7634e8c65a1SAlex Deucher * DCE 4.1 7644e8c65a1SAlex Deucher * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). 7654e8c65a1SAlex Deucher * Supports up to 6 digital outputs 7664e8c65a1SAlex Deucher * - 2 DIG encoder blocks. 7674e8c65a1SAlex Deucher * DIG1/2 can drive UNIPHY0/1/2 link A or link B 7684e8c65a1SAlex Deucher * 7691a66c95aSAlex Deucher * Routing 7701a66c95aSAlex Deucher * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) 7711a66c95aSAlex Deucher * Examples: 7721a66c95aSAlex Deucher * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI 7731a66c95aSAlex Deucher * crtc1 -> dig1 -> UNIPHY0 link B -> DP 7741a66c95aSAlex Deucher * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS 7751a66c95aSAlex Deucher * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI 7761a66c95aSAlex Deucher */ 777bcc1c2a1SAlex Deucher 778bcc1c2a1SAlex Deucher union dig_encoder_control { 779bcc1c2a1SAlex Deucher DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 780bcc1c2a1SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 781bcc1c2a1SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 782badbb57bSAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 783bcc1c2a1SAlex Deucher }; 784bcc1c2a1SAlex Deucher 785bcc1c2a1SAlex Deucher void 786558e27dbSAlex Deucher atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode) 787771fe6b9SJerome Glisse { 788771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 789771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 790771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 7919ae47867SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 7924aab97e8SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 793bcc1c2a1SAlex Deucher union dig_encoder_control args; 794d9c9fe36SAlex Deucher int index = 0; 795771fe6b9SJerome Glisse uint8_t frev, crev; 7964aab97e8SAlex Deucher int dp_clock = 0; 7974aab97e8SAlex Deucher int dp_lane_count = 0; 798badbb57bSAlex Deucher int hpd_id = RADEON_HPD_NONE; 799df271becSAlex Deucher int bpc = 8; 800771fe6b9SJerome Glisse 8014aab97e8SAlex Deucher if (connector) { 8024aab97e8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 8034aab97e8SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 8044aab97e8SAlex Deucher radeon_connector->con_priv; 8054aab97e8SAlex Deucher 8064aab97e8SAlex Deucher dp_clock = dig_connector->dp_clock; 8074aab97e8SAlex Deucher dp_lane_count = dig_connector->dp_lane_count; 808badbb57bSAlex Deucher hpd_id = radeon_connector->hpd.hpd; 809df271becSAlex Deucher bpc = connector->display_info.bpc; 8104aab97e8SAlex Deucher } 8114aab97e8SAlex Deucher 8124aab97e8SAlex Deucher /* no dig encoder assigned */ 8134aab97e8SAlex Deucher if (dig->dig_encoder == -1) 814771fe6b9SJerome Glisse return; 815771fe6b9SJerome Glisse 816771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 817771fe6b9SJerome Glisse 818bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) 819bcc1c2a1SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 820bcc1c2a1SAlex Deucher else { 821f28cf339SDave Airlie if (dig->dig_encoder) 822771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 823771fe6b9SJerome Glisse else 824771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 825bcc1c2a1SAlex Deucher } 826771fe6b9SJerome Glisse 827a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 828a084e6eeSAlex Deucher return; 829771fe6b9SJerome Glisse 830bcc1c2a1SAlex Deucher args.v1.ucAction = action; 831bcc1c2a1SAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 832558e27dbSAlex Deucher if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 833558e27dbSAlex Deucher args.v3.ucPanelMode = panel_mode; 834558e27dbSAlex Deucher else 835bcc1c2a1SAlex Deucher args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); 836771fe6b9SJerome Glisse 837badbb57bSAlex Deucher if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) || 838badbb57bSAlex Deucher (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) 8394aab97e8SAlex Deucher args.v1.ucLaneNum = dp_lane_count; 840badbb57bSAlex Deucher else if (radeon_encoder->pixel_clock > 165000) 841bcc1c2a1SAlex Deucher args.v1.ucLaneNum = 8; 842bcc1c2a1SAlex Deucher else 843bcc1c2a1SAlex Deucher args.v1.ucLaneNum = 4; 844bcc1c2a1SAlex Deucher 845badbb57bSAlex Deucher if (ASIC_IS_DCE5(rdev)) { 846badbb57bSAlex Deucher if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) || 847badbb57bSAlex Deucher (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST)) { 848badbb57bSAlex Deucher if (dp_clock == 270000) 849badbb57bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; 850badbb57bSAlex Deucher else if (dp_clock == 540000) 851badbb57bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; 852badbb57bSAlex Deucher } 853badbb57bSAlex Deucher args.v4.acConfig.ucDigSel = dig->dig_encoder; 854df271becSAlex Deucher switch (bpc) { 855df271becSAlex Deucher case 0: 856df271becSAlex Deucher args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; 857df271becSAlex Deucher break; 858df271becSAlex Deucher case 6: 859df271becSAlex Deucher args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; 860df271becSAlex Deucher break; 861df271becSAlex Deucher case 8: 862df271becSAlex Deucher default: 863badbb57bSAlex Deucher args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; 864df271becSAlex Deucher break; 865df271becSAlex Deucher case 10: 866df271becSAlex Deucher args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; 867df271becSAlex Deucher break; 868df271becSAlex Deucher case 12: 869df271becSAlex Deucher args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; 870df271becSAlex Deucher break; 871df271becSAlex Deucher case 16: 872df271becSAlex Deucher args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; 873df271becSAlex Deucher break; 874df271becSAlex Deucher } 875badbb57bSAlex Deucher if (hpd_id == RADEON_HPD_NONE) 876badbb57bSAlex Deucher args.v4.ucHPD_ID = 0; 877badbb57bSAlex Deucher else 878badbb57bSAlex Deucher args.v4.ucHPD_ID = hpd_id + 1; 879badbb57bSAlex Deucher } else if (ASIC_IS_DCE4(rdev)) { 880badbb57bSAlex Deucher if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000)) 881badbb57bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 882bcc1c2a1SAlex Deucher args.v3.acConfig.ucDigSel = dig->dig_encoder; 883df271becSAlex Deucher switch (bpc) { 884df271becSAlex Deucher case 0: 885df271becSAlex Deucher args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE; 886df271becSAlex Deucher break; 887df271becSAlex Deucher case 6: 888df271becSAlex Deucher args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR; 889df271becSAlex Deucher break; 890df271becSAlex Deucher case 8: 891df271becSAlex Deucher default: 892bcc1c2a1SAlex Deucher args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; 893df271becSAlex Deucher break; 894df271becSAlex Deucher case 10: 895df271becSAlex Deucher args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR; 896df271becSAlex Deucher break; 897df271becSAlex Deucher case 12: 898df271becSAlex Deucher args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR; 899df271becSAlex Deucher break; 900df271becSAlex Deucher case 16: 901df271becSAlex Deucher args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR; 902df271becSAlex Deucher break; 903df271becSAlex Deucher } 904771fe6b9SJerome Glisse } else { 905badbb57bSAlex Deucher if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) && (dp_clock == 270000)) 906badbb57bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 907771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 908771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 909bcc1c2a1SAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 910771fe6b9SJerome Glisse break; 911bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 912771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 913bcc1c2a1SAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 914bcc1c2a1SAlex Deucher break; 915bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 916bcc1c2a1SAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 917771fe6b9SJerome Glisse break; 918771fe6b9SJerome Glisse } 9195137ee94SAlex Deucher if (dig->linkb) 920bcc1c2a1SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 921771fe6b9SJerome Glisse else 922bcc1c2a1SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 923bcc1c2a1SAlex Deucher } 924771fe6b9SJerome Glisse 925771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 926771fe6b9SJerome Glisse 927771fe6b9SJerome Glisse } 928771fe6b9SJerome Glisse 929771fe6b9SJerome Glisse union dig_transmitter_control { 930771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 931771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 932bcc1c2a1SAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 933a001182aSAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; 934771fe6b9SJerome Glisse }; 935771fe6b9SJerome Glisse 9365801ead6SAlex Deucher void 9371a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) 938771fe6b9SJerome Glisse { 939771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 940771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 941771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 9429ae47867SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 943ac89af1eSAlex Deucher struct drm_connector *connector; 944771fe6b9SJerome Glisse union dig_transmitter_control args; 945d9c9fe36SAlex Deucher int index = 0; 946771fe6b9SJerome Glisse uint8_t frev, crev; 947f92a8b67SAlex Deucher bool is_dp = false; 948bcc1c2a1SAlex Deucher int pll_id = 0; 9494aab97e8SAlex Deucher int dp_clock = 0; 9504aab97e8SAlex Deucher int dp_lane_count = 0; 9514aab97e8SAlex Deucher int connector_object_id = 0; 9524aab97e8SAlex Deucher int igp_lane_info = 0; 953f3aeceacSAlex Deucher int dig_encoder = dig->dig_encoder; 954771fe6b9SJerome Glisse 955f3aeceacSAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 956ac89af1eSAlex Deucher connector = radeon_get_connector_for_encoder_init(encoder); 957f3aeceacSAlex Deucher /* just needed to avoid bailing in the encoder check. the encoder 958f3aeceacSAlex Deucher * isn't used for init 959f3aeceacSAlex Deucher */ 960f3aeceacSAlex Deucher dig_encoder = 0; 961f3aeceacSAlex Deucher } else 962ac89af1eSAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 963ac89af1eSAlex Deucher 9644aab97e8SAlex Deucher if (connector) { 9654aab97e8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 9664aab97e8SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 9674aab97e8SAlex Deucher radeon_connector->con_priv; 9684aab97e8SAlex Deucher 9694aab97e8SAlex Deucher dp_clock = dig_connector->dp_clock; 9704aab97e8SAlex Deucher dp_lane_count = dig_connector->dp_lane_count; 9714aab97e8SAlex Deucher connector_object_id = 9724aab97e8SAlex Deucher (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 9734aab97e8SAlex Deucher igp_lane_info = dig_connector->igp_lane_info; 9744aab97e8SAlex Deucher } 9754aab97e8SAlex Deucher 9764aab97e8SAlex Deucher /* no dig encoder assigned */ 977f3aeceacSAlex Deucher if (dig_encoder == -1) 9789ae47867SAlex Deucher return; 9799ae47867SAlex Deucher 980f92a8b67SAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) 981f92a8b67SAlex Deucher is_dp = true; 982f92a8b67SAlex Deucher 983771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 984771fe6b9SJerome Glisse 985771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 98699999aaaSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 98799999aaaSAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 98899999aaaSAlex Deucher break; 989771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 9904aab97e8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 9914aab97e8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 9924aab97e8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 993771fe6b9SJerome Glisse break; 994771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 9954aab97e8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); 996771fe6b9SJerome Glisse break; 997771fe6b9SJerome Glisse } 998771fe6b9SJerome Glisse 999a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1000a084e6eeSAlex Deucher return; 1001771fe6b9SJerome Glisse 1002771fe6b9SJerome Glisse args.v1.ucAction = action; 1003f95a9f0bSAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 10044589433cSCédric Cano args.v1.usInitInfo = cpu_to_le16(connector_object_id); 10051a66c95aSAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 10061a66c95aSAlex Deucher args.v1.asMode.ucLaneSel = lane_num; 10071a66c95aSAlex Deucher args.v1.asMode.ucLaneSet = lane_set; 1008771fe6b9SJerome Glisse } else { 1009f92a8b67SAlex Deucher if (is_dp) 1010f92a8b67SAlex Deucher args.v1.usPixelClock = 10114aab97e8SAlex Deucher cpu_to_le16(dp_clock / 10); 1012f92a8b67SAlex Deucher else if (radeon_encoder->pixel_clock > 165000) 1013f95a9f0bSAlex Deucher args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1014f95a9f0bSAlex Deucher else 1015f95a9f0bSAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1016771fe6b9SJerome Glisse } 1017bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 1018bcc1c2a1SAlex Deucher if (is_dp) 10194aab97e8SAlex Deucher args.v3.ucLaneNum = dp_lane_count; 1020bcc1c2a1SAlex Deucher else if (radeon_encoder->pixel_clock > 165000) 1021bcc1c2a1SAlex Deucher args.v3.ucLaneNum = 8; 1022bcc1c2a1SAlex Deucher else 1023bcc1c2a1SAlex Deucher args.v3.ucLaneNum = 4; 1024bcc1c2a1SAlex Deucher 102596b3bef8SAlex Deucher if (dig->linkb) 1026bcc1c2a1SAlex Deucher args.v3.acConfig.ucLinkSel = 1; 1027f3aeceacSAlex Deucher if (dig_encoder & 1) 1028bcc1c2a1SAlex Deucher args.v3.acConfig.ucEncoderSel = 1; 1029bcc1c2a1SAlex Deucher 1030bcc1c2a1SAlex Deucher /* Select the PLL for the PHY 1031bcc1c2a1SAlex Deucher * DP PHY should be clocked from external src if there is 1032bcc1c2a1SAlex Deucher * one. 1033bcc1c2a1SAlex Deucher */ 1034bcc1c2a1SAlex Deucher if (encoder->crtc) { 1035bcc1c2a1SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1036bcc1c2a1SAlex Deucher pll_id = radeon_crtc->pll_id; 1037bcc1c2a1SAlex Deucher } 1038a001182aSAlex Deucher 1039a001182aSAlex Deucher if (ASIC_IS_DCE5(rdev)) { 104086a94defSAlex Deucher /* On DCE5 DCPLL usually generates the DP ref clock */ 104186a94defSAlex Deucher if (is_dp) { 104286a94defSAlex Deucher if (rdev->clock.dp_extclk) 104386a94defSAlex Deucher args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK; 1044a001182aSAlex Deucher else 104586a94defSAlex Deucher args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL; 104686a94defSAlex Deucher } else 1047a001182aSAlex Deucher args.v4.acConfig.ucRefClkSource = pll_id; 1048a001182aSAlex Deucher } else { 104986a94defSAlex Deucher /* On DCE4, if there is an external clock, it generates the DP ref clock */ 1050bcc1c2a1SAlex Deucher if (is_dp && rdev->clock.dp_extclk) 1051bcc1c2a1SAlex Deucher args.v3.acConfig.ucRefClkSource = 2; /* external src */ 1052bcc1c2a1SAlex Deucher else 1053bcc1c2a1SAlex Deucher args.v3.acConfig.ucRefClkSource = pll_id; 1054a001182aSAlex Deucher } 1055bcc1c2a1SAlex Deucher 1056bcc1c2a1SAlex Deucher switch (radeon_encoder->encoder_id) { 1057bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1058bcc1c2a1SAlex Deucher args.v3.acConfig.ucTransmitterSel = 0; 1059bcc1c2a1SAlex Deucher break; 1060bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1061bcc1c2a1SAlex Deucher args.v3.acConfig.ucTransmitterSel = 1; 1062bcc1c2a1SAlex Deucher break; 1063bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1064bcc1c2a1SAlex Deucher args.v3.acConfig.ucTransmitterSel = 2; 1065bcc1c2a1SAlex Deucher break; 1066bcc1c2a1SAlex Deucher } 1067bcc1c2a1SAlex Deucher 1068bcc1c2a1SAlex Deucher if (is_dp) 1069bcc1c2a1SAlex Deucher args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ 1070bcc1c2a1SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1071bcc1c2a1SAlex Deucher if (dig->coherent_mode) 1072bcc1c2a1SAlex Deucher args.v3.acConfig.fCoherentMode = 1; 1073b317a9ceSAlex Deucher if (radeon_encoder->pixel_clock > 165000) 1074b317a9ceSAlex Deucher args.v3.acConfig.fDualLinkConnector = 1; 1075bcc1c2a1SAlex Deucher } 1076bcc1c2a1SAlex Deucher } else if (ASIC_IS_DCE32(rdev)) { 1077f3aeceacSAlex Deucher args.v2.acConfig.ucEncoderSel = dig_encoder; 10785137ee94SAlex Deucher if (dig->linkb) 10791a66c95aSAlex Deucher args.v2.acConfig.ucLinkSel = 1; 1080771fe6b9SJerome Glisse 1081771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1082771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1083771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 0; 1084771fe6b9SJerome Glisse break; 1085771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1086771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 1; 1087771fe6b9SJerome Glisse break; 1088771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1089771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 2; 1090771fe6b9SJerome Glisse break; 1091771fe6b9SJerome Glisse } 1092771fe6b9SJerome Glisse 109374d074eeSAlex Deucher if (is_dp) { 1094f92a8b67SAlex Deucher args.v2.acConfig.fCoherentMode = 1; 109574d074eeSAlex Deucher args.v2.acConfig.fDPConnector = 1; 109674d074eeSAlex Deucher } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1097771fe6b9SJerome Glisse if (dig->coherent_mode) 1098771fe6b9SJerome Glisse args.v2.acConfig.fCoherentMode = 1; 1099b317a9ceSAlex Deucher if (radeon_encoder->pixel_clock > 165000) 1100b317a9ceSAlex Deucher args.v2.acConfig.fDualLinkConnector = 1; 1101771fe6b9SJerome Glisse } 1102771fe6b9SJerome Glisse } else { 1103771fe6b9SJerome Glisse args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 1104771fe6b9SJerome Glisse 1105f3aeceacSAlex Deucher if (dig_encoder) 11061a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 11071a66c95aSAlex Deucher else 1108771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 1109f28cf339SDave Airlie 1110d9c9fe36SAlex Deucher if ((rdev->flags & RADEON_IS_IGP) && 1111d9c9fe36SAlex Deucher (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 1112d9c9fe36SAlex Deucher if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { 11134aab97e8SAlex Deucher if (igp_lane_info & 0x1) 1114771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 11154aab97e8SAlex Deucher else if (igp_lane_info & 0x2) 1116771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 11174aab97e8SAlex Deucher else if (igp_lane_info & 0x4) 1118771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 11194aab97e8SAlex Deucher else if (igp_lane_info & 0x8) 1120771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 1121d9c9fe36SAlex Deucher } else { 11224aab97e8SAlex Deucher if (igp_lane_info & 0x3) 1123d9c9fe36SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 11244aab97e8SAlex Deucher else if (igp_lane_info & 0xc) 1125d9c9fe36SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 1126771fe6b9SJerome Glisse } 1127771fe6b9SJerome Glisse } 11281a66c95aSAlex Deucher 11295137ee94SAlex Deucher if (dig->linkb) 11301a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 11311a66c95aSAlex Deucher else 11321a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 11331a66c95aSAlex Deucher 1134f92a8b67SAlex Deucher if (is_dp) 1135f92a8b67SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1136f92a8b67SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1137771fe6b9SJerome Glisse if (dig->coherent_mode) 1138771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1139d9c9fe36SAlex Deucher if (radeon_encoder->pixel_clock > 165000) 1140d9c9fe36SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 1141771fe6b9SJerome Glisse } 1142771fe6b9SJerome Glisse } 1143771fe6b9SJerome Glisse 1144771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1145771fe6b9SJerome Glisse } 1146771fe6b9SJerome Glisse 11472dafb74dSAlex Deucher bool 11488b834852SAlex Deucher atombios_set_edp_panel_power(struct drm_connector *connector, int action) 11498b834852SAlex Deucher { 11508b834852SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 11518b834852SAlex Deucher struct drm_device *dev = radeon_connector->base.dev; 11528b834852SAlex Deucher struct radeon_device *rdev = dev->dev_private; 11538b834852SAlex Deucher union dig_transmitter_control args; 11548b834852SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 11558b834852SAlex Deucher uint8_t frev, crev; 11568b834852SAlex Deucher 11578b834852SAlex Deucher if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) 11582dafb74dSAlex Deucher goto done; 11598b834852SAlex Deucher 11608b834852SAlex Deucher if (!ASIC_IS_DCE4(rdev)) 11612dafb74dSAlex Deucher goto done; 11628b834852SAlex Deucher 1163e468e001SStefan Weil if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) && 11648b834852SAlex Deucher (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) 11652dafb74dSAlex Deucher goto done; 11668b834852SAlex Deucher 11678b834852SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 11682dafb74dSAlex Deucher goto done; 11698b834852SAlex Deucher 11708b834852SAlex Deucher memset(&args, 0, sizeof(args)); 11718b834852SAlex Deucher 11728b834852SAlex Deucher args.v1.ucAction = action; 11738b834852SAlex Deucher 11748b834852SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 11752dafb74dSAlex Deucher 11762dafb74dSAlex Deucher /* wait for the panel to power up */ 11772dafb74dSAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) { 11782dafb74dSAlex Deucher int i; 11792dafb74dSAlex Deucher 11802dafb74dSAlex Deucher for (i = 0; i < 300; i++) { 11812dafb74dSAlex Deucher if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) 11822dafb74dSAlex Deucher return true; 11832dafb74dSAlex Deucher mdelay(1); 11842dafb74dSAlex Deucher } 11852dafb74dSAlex Deucher return false; 11862dafb74dSAlex Deucher } 11872dafb74dSAlex Deucher done: 11882dafb74dSAlex Deucher return true; 11898b834852SAlex Deucher } 11908b834852SAlex Deucher 11913e4b9982SAlex Deucher union external_encoder_control { 11923e4b9982SAlex Deucher EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 1193bf982ebfSAlex Deucher EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 11943e4b9982SAlex Deucher }; 11953e4b9982SAlex Deucher 11963e4b9982SAlex Deucher static void 11973e4b9982SAlex Deucher atombios_external_encoder_setup(struct drm_encoder *encoder, 11983e4b9982SAlex Deucher struct drm_encoder *ext_encoder, 11993e4b9982SAlex Deucher int action) 12003e4b9982SAlex Deucher { 12013e4b9982SAlex Deucher struct drm_device *dev = encoder->dev; 12023e4b9982SAlex Deucher struct radeon_device *rdev = dev->dev_private; 12033e4b9982SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1204bf982ebfSAlex Deucher struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); 12053e4b9982SAlex Deucher union external_encoder_control args; 1206ac89af1eSAlex Deucher struct drm_connector *connector; 12073e4b9982SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 12083e4b9982SAlex Deucher u8 frev, crev; 12093e4b9982SAlex Deucher int dp_clock = 0; 12103e4b9982SAlex Deucher int dp_lane_count = 0; 12113e4b9982SAlex Deucher int connector_object_id = 0; 1212bf982ebfSAlex Deucher u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1213df271becSAlex Deucher int bpc = 8; 12143e4b9982SAlex Deucher 1215ac89af1eSAlex Deucher if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) 1216ac89af1eSAlex Deucher connector = radeon_get_connector_for_encoder_init(encoder); 1217ac89af1eSAlex Deucher else 1218ac89af1eSAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 1219ac89af1eSAlex Deucher 12203e4b9982SAlex Deucher if (connector) { 12213e4b9982SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 12223e4b9982SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 12233e4b9982SAlex Deucher radeon_connector->con_priv; 12243e4b9982SAlex Deucher 12253e4b9982SAlex Deucher dp_clock = dig_connector->dp_clock; 12263e4b9982SAlex Deucher dp_lane_count = dig_connector->dp_lane_count; 12273e4b9982SAlex Deucher connector_object_id = 12283e4b9982SAlex Deucher (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1229df271becSAlex Deucher bpc = connector->display_info.bpc; 12303e4b9982SAlex Deucher } 12313e4b9982SAlex Deucher 12323e4b9982SAlex Deucher memset(&args, 0, sizeof(args)); 12333e4b9982SAlex Deucher 12343e4b9982SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 12353e4b9982SAlex Deucher return; 12363e4b9982SAlex Deucher 12373e4b9982SAlex Deucher switch (frev) { 12383e4b9982SAlex Deucher case 1: 12393e4b9982SAlex Deucher /* no params on frev 1 */ 12403e4b9982SAlex Deucher break; 12413e4b9982SAlex Deucher case 2: 12423e4b9982SAlex Deucher switch (crev) { 12433e4b9982SAlex Deucher case 1: 12443e4b9982SAlex Deucher case 2: 12453e4b9982SAlex Deucher args.v1.sDigEncoder.ucAction = action; 12463e4b9982SAlex Deucher args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 12473e4b9982SAlex Deucher args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); 12483e4b9982SAlex Deucher 12493e4b9982SAlex Deucher if (args.v1.sDigEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 12503e4b9982SAlex Deucher if (dp_clock == 270000) 12513e4b9982SAlex Deucher args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 12523e4b9982SAlex Deucher args.v1.sDigEncoder.ucLaneNum = dp_lane_count; 12533e4b9982SAlex Deucher } else if (radeon_encoder->pixel_clock > 165000) 12543e4b9982SAlex Deucher args.v1.sDigEncoder.ucLaneNum = 8; 12553e4b9982SAlex Deucher else 12563e4b9982SAlex Deucher args.v1.sDigEncoder.ucLaneNum = 4; 12573e4b9982SAlex Deucher break; 1258bf982ebfSAlex Deucher case 3: 1259bf982ebfSAlex Deucher args.v3.sExtEncoder.ucAction = action; 1260bf982ebfSAlex Deucher if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) 12614589433cSCédric Cano args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id); 1262bf982ebfSAlex Deucher else 1263bf982ebfSAlex Deucher args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1264bf982ebfSAlex Deucher args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); 1265bf982ebfSAlex Deucher 1266bf982ebfSAlex Deucher if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 1267bf982ebfSAlex Deucher if (dp_clock == 270000) 1268bf982ebfSAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 1269bf982ebfSAlex Deucher else if (dp_clock == 540000) 1270bf982ebfSAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 1271bf982ebfSAlex Deucher args.v3.sExtEncoder.ucLaneNum = dp_lane_count; 1272bf982ebfSAlex Deucher } else if (radeon_encoder->pixel_clock > 165000) 1273bf982ebfSAlex Deucher args.v3.sExtEncoder.ucLaneNum = 8; 1274bf982ebfSAlex Deucher else 1275bf982ebfSAlex Deucher args.v3.sExtEncoder.ucLaneNum = 4; 1276bf982ebfSAlex Deucher switch (ext_enum) { 1277bf982ebfSAlex Deucher case GRAPH_OBJECT_ENUM_ID1: 1278bf982ebfSAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 1279bf982ebfSAlex Deucher break; 1280bf982ebfSAlex Deucher case GRAPH_OBJECT_ENUM_ID2: 1281bf982ebfSAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 1282bf982ebfSAlex Deucher break; 1283bf982ebfSAlex Deucher case GRAPH_OBJECT_ENUM_ID3: 1284bf982ebfSAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 1285bf982ebfSAlex Deucher break; 1286bf982ebfSAlex Deucher } 1287df271becSAlex Deucher switch (bpc) { 1288df271becSAlex Deucher case 0: 1289df271becSAlex Deucher args.v3.sExtEncoder.ucBitPerColor = PANEL_BPC_UNDEFINE; 1290df271becSAlex Deucher break; 1291df271becSAlex Deucher case 6: 1292df271becSAlex Deucher args.v3.sExtEncoder.ucBitPerColor = PANEL_6BIT_PER_COLOR; 1293df271becSAlex Deucher break; 1294df271becSAlex Deucher case 8: 1295df271becSAlex Deucher default: 1296bf982ebfSAlex Deucher args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR; 1297bf982ebfSAlex Deucher break; 1298df271becSAlex Deucher case 10: 1299df271becSAlex Deucher args.v3.sExtEncoder.ucBitPerColor = PANEL_10BIT_PER_COLOR; 1300df271becSAlex Deucher break; 1301df271becSAlex Deucher case 12: 1302df271becSAlex Deucher args.v3.sExtEncoder.ucBitPerColor = PANEL_12BIT_PER_COLOR; 1303df271becSAlex Deucher break; 1304df271becSAlex Deucher case 16: 1305df271becSAlex Deucher args.v3.sExtEncoder.ucBitPerColor = PANEL_16BIT_PER_COLOR; 1306df271becSAlex Deucher break; 1307df271becSAlex Deucher } 1308df271becSAlex Deucher break; 13093e4b9982SAlex Deucher default: 13103e4b9982SAlex Deucher DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 13113e4b9982SAlex Deucher return; 13123e4b9982SAlex Deucher } 13133e4b9982SAlex Deucher break; 13143e4b9982SAlex Deucher default: 13153e4b9982SAlex Deucher DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 13163e4b9982SAlex Deucher return; 13173e4b9982SAlex Deucher } 13183e4b9982SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 13193e4b9982SAlex Deucher } 13203e4b9982SAlex Deucher 1321771fe6b9SJerome Glisse static void 1322771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable) 1323771fe6b9SJerome Glisse { 1324771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1325771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1326771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1327771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1328771fe6b9SJerome Glisse ENABLE_YUV_PS_ALLOCATION args; 1329771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 1330771fe6b9SJerome Glisse uint32_t temp, reg; 1331771fe6b9SJerome Glisse 1332771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1333771fe6b9SJerome Glisse 1334771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 1335771fe6b9SJerome Glisse reg = R600_BIOS_3_SCRATCH; 1336771fe6b9SJerome Glisse else 1337771fe6b9SJerome Glisse reg = RADEON_BIOS_3_SCRATCH; 1338771fe6b9SJerome Glisse 1339771fe6b9SJerome Glisse /* XXX: fix up scratch reg handling */ 1340771fe6b9SJerome Glisse temp = RREG32(reg); 13414ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1342771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_TV1_ACTIVE | 1343771fe6b9SJerome Glisse (radeon_crtc->crtc_id << 18))); 13444ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1345771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); 1346771fe6b9SJerome Glisse else 1347771fe6b9SJerome Glisse WREG32(reg, 0); 1348771fe6b9SJerome Glisse 1349771fe6b9SJerome Glisse if (enable) 1350771fe6b9SJerome Glisse args.ucEnable = ATOM_ENABLE; 1351771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 1352771fe6b9SJerome Glisse 1353771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1354771fe6b9SJerome Glisse 1355771fe6b9SJerome Glisse WREG32(reg, temp); 1356771fe6b9SJerome Glisse } 1357771fe6b9SJerome Glisse 1358771fe6b9SJerome Glisse static void 1359771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) 1360771fe6b9SJerome Glisse { 1361771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1362771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1363771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 13643e4b9982SAlex Deucher struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); 1365771fe6b9SJerome Glisse DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1366771fe6b9SJerome Glisse int index = 0; 1367771fe6b9SJerome Glisse bool is_dig = false; 136869c74525SAlex Deucher bool is_dce5_dac = false; 1369d07f4e83SAlex Deucher bool is_dce5_dvo = false; 1370771fe6b9SJerome Glisse 1371771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1372771fe6b9SJerome Glisse 1373d9fdaafbSDave Airlie DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 13744ce001abSDave Airlie radeon_encoder->encoder_id, mode, radeon_encoder->devices, 13754ce001abSDave Airlie radeon_encoder->active_device); 1376771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1377771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1378771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1379771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1380771fe6b9SJerome Glisse break; 1381771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1382771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1383771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1384771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1385771fe6b9SJerome Glisse is_dig = true; 1386771fe6b9SJerome Glisse break; 1387771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1388771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 138999999aaaSAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 139099999aaaSAlex Deucher break; 1391771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1392d07f4e83SAlex Deucher if (ASIC_IS_DCE5(rdev)) 1393d07f4e83SAlex Deucher is_dce5_dvo = true; 1394d07f4e83SAlex Deucher else if (ASIC_IS_DCE3(rdev)) 139599999aaaSAlex Deucher is_dig = true; 139699999aaaSAlex Deucher else 1397771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1398771fe6b9SJerome Glisse break; 1399771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1400771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1401771fe6b9SJerome Glisse break; 1402771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1403771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1404771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1405771fe6b9SJerome Glisse else 1406771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1407771fe6b9SJerome Glisse break; 1408771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1409771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 141069c74525SAlex Deucher if (ASIC_IS_DCE5(rdev)) 141169c74525SAlex Deucher is_dce5_dac = true; 141269c74525SAlex Deucher else { 14138c2a6d73SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1414771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 14158c2a6d73SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1416771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1417771fe6b9SJerome Glisse else 1418771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 141969c74525SAlex Deucher } 1420771fe6b9SJerome Glisse break; 1421771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1422771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 14238c2a6d73SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1424771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 14258c2a6d73SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1426771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1427771fe6b9SJerome Glisse else 1428771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1429771fe6b9SJerome Glisse break; 1430771fe6b9SJerome Glisse } 1431771fe6b9SJerome Glisse 1432771fe6b9SJerome Glisse if (is_dig) { 1433771fe6b9SJerome Glisse switch (mode) { 1434771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 14358323fa6bSAlex Deucher /* some early dce3.2 boards have a bug in their transmitter control table */ 14368323fa6bSAlex Deucher if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) 14378323fa6bSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 14388323fa6bSAlex Deucher else 1439a5f798ceSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); 1440fb668c2fSAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { 144158682f10SDave Airlie struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1442fb668c2fSAlex Deucher 14438b834852SAlex Deucher if (connector && 14448b834852SAlex Deucher (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { 14458b834852SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 14468b834852SAlex Deucher struct radeon_connector_atom_dig *radeon_dig_connector = 14478b834852SAlex Deucher radeon_connector->con_priv; 14488b834852SAlex Deucher atombios_set_edp_panel_power(connector, 14498b834852SAlex Deucher ATOM_TRANSMITTER_ACTION_POWER_ON); 14508b834852SAlex Deucher radeon_dig_connector->edp_on = true; 14518b834852SAlex Deucher } 1452224d94b1SAlex Deucher if (ASIC_IS_DCE4(rdev)) 1453224d94b1SAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 1454224d94b1SAlex Deucher radeon_dp_link_train(encoder, connector); 1455fb668c2fSAlex Deucher if (ASIC_IS_DCE4(rdev)) 1456558e27dbSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 145758682f10SDave Airlie } 1458ba251bdeSAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1459ba251bdeSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); 1460771fe6b9SJerome Glisse break; 1461771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 1462771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 1463771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 146458682f10SDave Airlie atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); 1465fb668c2fSAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { 14668b834852SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 14678b834852SAlex Deucher 1468fb668c2fSAlex Deucher if (ASIC_IS_DCE4(rdev)) 1469558e27dbSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 14708b834852SAlex Deucher if (connector && 14718b834852SAlex Deucher (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { 14728b834852SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 14738b834852SAlex Deucher struct radeon_connector_atom_dig *radeon_dig_connector = 14748b834852SAlex Deucher radeon_connector->con_priv; 14758b834852SAlex Deucher atombios_set_edp_panel_power(connector, 14768b834852SAlex Deucher ATOM_TRANSMITTER_ACTION_POWER_OFF); 14778b834852SAlex Deucher radeon_dig_connector->edp_on = false; 14788b834852SAlex Deucher } 1479fb668c2fSAlex Deucher } 1480ba251bdeSAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1481ba251bdeSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); 1482771fe6b9SJerome Glisse break; 1483771fe6b9SJerome Glisse } 148469c74525SAlex Deucher } else if (is_dce5_dac) { 148569c74525SAlex Deucher switch (mode) { 148669c74525SAlex Deucher case DRM_MODE_DPMS_ON: 148769c74525SAlex Deucher atombios_dac_setup(encoder, ATOM_ENABLE); 148869c74525SAlex Deucher break; 148969c74525SAlex Deucher case DRM_MODE_DPMS_STANDBY: 149069c74525SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 149169c74525SAlex Deucher case DRM_MODE_DPMS_OFF: 149269c74525SAlex Deucher atombios_dac_setup(encoder, ATOM_DISABLE); 149369c74525SAlex Deucher break; 149469c74525SAlex Deucher } 1495d07f4e83SAlex Deucher } else if (is_dce5_dvo) { 1496d07f4e83SAlex Deucher switch (mode) { 1497d07f4e83SAlex Deucher case DRM_MODE_DPMS_ON: 1498d07f4e83SAlex Deucher atombios_dvo_setup(encoder, ATOM_ENABLE); 1499d07f4e83SAlex Deucher break; 1500d07f4e83SAlex Deucher case DRM_MODE_DPMS_STANDBY: 1501d07f4e83SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 1502d07f4e83SAlex Deucher case DRM_MODE_DPMS_OFF: 1503d07f4e83SAlex Deucher atombios_dvo_setup(encoder, ATOM_DISABLE); 1504d07f4e83SAlex Deucher break; 1505d07f4e83SAlex Deucher } 1506771fe6b9SJerome Glisse } else { 1507771fe6b9SJerome Glisse switch (mode) { 1508771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 1509771fe6b9SJerome Glisse args.ucAction = ATOM_ENABLE; 1510fdfc6159SAlex Deucher /* workaround for DVOOutputControl on some RS690 systems */ 1511fdfc6159SAlex Deucher if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) { 1512fdfc6159SAlex Deucher u32 reg = RREG32(RADEON_BIOS_3_SCRATCH); 1513fdfc6159SAlex Deucher WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE); 1514fdfc6159SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1515fdfc6159SAlex Deucher WREG32(RADEON_BIOS_3_SCRATCH, reg); 1516fdfc6159SAlex Deucher } else 1517ba251bdeSAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1518ba251bdeSAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1519ba251bdeSAlex Deucher args.ucAction = ATOM_LCD_BLON; 1520ba251bdeSAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1521ba251bdeSAlex Deucher } 1522771fe6b9SJerome Glisse break; 1523771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 1524771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 1525771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 1526771fe6b9SJerome Glisse args.ucAction = ATOM_DISABLE; 1527ba251bdeSAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1528ba251bdeSAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1529ba251bdeSAlex Deucher args.ucAction = ATOM_LCD_BLOFF; 1530ba251bdeSAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1531ba251bdeSAlex Deucher } 1532771fe6b9SJerome Glisse break; 1533771fe6b9SJerome Glisse } 1534771fe6b9SJerome Glisse } 15353e4b9982SAlex Deucher 15363e4b9982SAlex Deucher if (ext_encoder) { 15373e4b9982SAlex Deucher switch (mode) { 15383e4b9982SAlex Deucher case DRM_MODE_DPMS_ON: 15393e4b9982SAlex Deucher default: 1540d6c66952SAlex Deucher if (ASIC_IS_DCE41(rdev)) { 1541d6c66952SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 1542d6c66952SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); 1543d6c66952SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 1544d6c66952SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); 1545d6c66952SAlex Deucher } else 1546d6c66952SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); 15473e4b9982SAlex Deucher break; 15483e4b9982SAlex Deucher case DRM_MODE_DPMS_STANDBY: 15493e4b9982SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 15503e4b9982SAlex Deucher case DRM_MODE_DPMS_OFF: 1551d6c66952SAlex Deucher if (ASIC_IS_DCE41(rdev)) { 1552d6c66952SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 1553d6c66952SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); 1554d6c66952SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 1555d6c66952SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); 1556d6c66952SAlex Deucher } else 1557d6c66952SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); 15583e4b9982SAlex Deucher break; 15593e4b9982SAlex Deucher } 15603e4b9982SAlex Deucher } 15613e4b9982SAlex Deucher 1562771fe6b9SJerome Glisse radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1563c913e23aSRafał Miłecki 1564771fe6b9SJerome Glisse } 1565771fe6b9SJerome Glisse 15669ae47867SAlex Deucher union crtc_source_param { 1567771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 1568771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 1569771fe6b9SJerome Glisse }; 1570771fe6b9SJerome Glisse 1571771fe6b9SJerome Glisse static void 1572771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder) 1573771fe6b9SJerome Glisse { 1574771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1575771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1576771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1577771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 15789ae47867SAlex Deucher union crtc_source_param args; 1579771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1580771fe6b9SJerome Glisse uint8_t frev, crev; 1581f28cf339SDave Airlie struct radeon_encoder_atom_dig *dig; 1582771fe6b9SJerome Glisse 1583771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1584771fe6b9SJerome Glisse 1585a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1586a084e6eeSAlex Deucher return; 1587771fe6b9SJerome Glisse 1588771fe6b9SJerome Glisse switch (frev) { 1589771fe6b9SJerome Glisse case 1: 1590771fe6b9SJerome Glisse switch (crev) { 1591771fe6b9SJerome Glisse case 1: 1592771fe6b9SJerome Glisse default: 1593771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 1594771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 1595771fe6b9SJerome Glisse else { 1596771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { 1597771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 1598771fe6b9SJerome Glisse } else { 1599771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id << 2; 1600771fe6b9SJerome Glisse } 1601771fe6b9SJerome Glisse } 1602771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1603771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1604771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1605771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1606771fe6b9SJerome Glisse break; 1607771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1608771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1609771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) 1610771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1611771fe6b9SJerome Glisse else 1612771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1613771fe6b9SJerome Glisse break; 1614771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1615771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1616771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1617771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1618771fe6b9SJerome Glisse break; 1619771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1620771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 16214ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1622771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 16234ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1624771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1625771fe6b9SJerome Glisse else 1626771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1627771fe6b9SJerome Glisse break; 1628771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1629771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 16304ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1631771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 16324ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1633771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1634771fe6b9SJerome Glisse else 1635771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1636771fe6b9SJerome Glisse break; 1637771fe6b9SJerome Glisse } 1638771fe6b9SJerome Glisse break; 1639771fe6b9SJerome Glisse case 2: 1640771fe6b9SJerome Glisse args.v2.ucCRTC = radeon_crtc->crtc_id; 1641*1d33e1fcSAlex Deucher if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) { 1642a4863ca9SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1643a4863ca9SAlex Deucher 1644a4863ca9SAlex Deucher if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) 1645a4863ca9SAlex Deucher args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; 1646a4863ca9SAlex Deucher else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA) 1647a4863ca9SAlex Deucher args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; 1648a4863ca9SAlex Deucher else 1649a4863ca9SAlex Deucher args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1650a4863ca9SAlex Deucher } else 1651771fe6b9SJerome Glisse args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1652771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1653771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1654771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1655771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1656f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1657f28cf339SDave Airlie dig = radeon_encoder->enc_priv; 1658bcc1c2a1SAlex Deucher switch (dig->dig_encoder) { 1659bcc1c2a1SAlex Deucher case 0: 1660771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1661771fe6b9SJerome Glisse break; 1662bcc1c2a1SAlex Deucher case 1: 1663bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1664bcc1c2a1SAlex Deucher break; 1665bcc1c2a1SAlex Deucher case 2: 1666bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 1667bcc1c2a1SAlex Deucher break; 1668bcc1c2a1SAlex Deucher case 3: 1669bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 1670bcc1c2a1SAlex Deucher break; 1671bcc1c2a1SAlex Deucher case 4: 1672bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 1673bcc1c2a1SAlex Deucher break; 1674bcc1c2a1SAlex Deucher case 5: 1675bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 1676bcc1c2a1SAlex Deucher break; 1677bcc1c2a1SAlex Deucher } 1678bcc1c2a1SAlex Deucher break; 1679771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1680771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 1681771fe6b9SJerome Glisse break; 1682771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 16834ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1684771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 16854ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1686771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1687771fe6b9SJerome Glisse else 1688771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1689771fe6b9SJerome Glisse break; 1690771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 16914ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1692771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 16934ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1694771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1695771fe6b9SJerome Glisse else 1696771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1697771fe6b9SJerome Glisse break; 1698771fe6b9SJerome Glisse } 1699771fe6b9SJerome Glisse break; 1700771fe6b9SJerome Glisse } 1701771fe6b9SJerome Glisse break; 1702771fe6b9SJerome Glisse default: 1703771fe6b9SJerome Glisse DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 170499999aaaSAlex Deucher return; 1705771fe6b9SJerome Glisse } 1706771fe6b9SJerome Glisse 1707771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1708267364acSAlex Deucher 1709267364acSAlex Deucher /* update scratch regs with new routing */ 1710267364acSAlex Deucher radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1711771fe6b9SJerome Glisse } 1712771fe6b9SJerome Glisse 1713771fe6b9SJerome Glisse static void 1714771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder, 1715771fe6b9SJerome Glisse struct drm_display_mode *mode) 1716771fe6b9SJerome Glisse { 1717771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1718771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1719771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1720771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1721771fe6b9SJerome Glisse 1722771fe6b9SJerome Glisse /* Funky macbooks */ 1723771fe6b9SJerome Glisse if ((dev->pdev->device == 0x71C5) && 1724771fe6b9SJerome Glisse (dev->pdev->subsystem_vendor == 0x106b) && 1725771fe6b9SJerome Glisse (dev->pdev->subsystem_device == 0x0080)) { 1726771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1727771fe6b9SJerome Glisse uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1728771fe6b9SJerome Glisse 1729771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1730771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1731771fe6b9SJerome Glisse 1732771fe6b9SJerome Glisse WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1733771fe6b9SJerome Glisse } 1734771fe6b9SJerome Glisse } 1735771fe6b9SJerome Glisse 1736771fe6b9SJerome Glisse /* set scaler clears this on some chips */ 1737c9417bddSAlex Deucher if (ASIC_IS_AVIVO(rdev) && 1738c9417bddSAlex Deucher (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) { 1739c9417bddSAlex Deucher if (ASIC_IS_DCE4(rdev)) { 1740c9417bddSAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) 1741c9417bddSAlex Deucher WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 1742c9417bddSAlex Deucher EVERGREEN_INTERLEAVE_EN); 1743c9417bddSAlex Deucher else 1744c9417bddSAlex Deucher WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 1745c9417bddSAlex Deucher } else { 1746c9417bddSAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) 1747ceefedd8SAlex Deucher WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 1748ceefedd8SAlex Deucher AVIVO_D1MODE_INTERLEAVE_EN); 1749c9417bddSAlex Deucher else 1750c9417bddSAlex Deucher WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 1751c9417bddSAlex Deucher } 1752ceefedd8SAlex Deucher } 1753771fe6b9SJerome Glisse } 1754771fe6b9SJerome Glisse 1755f28cf339SDave Airlie static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) 1756f28cf339SDave Airlie { 1757f28cf339SDave Airlie struct drm_device *dev = encoder->dev; 1758f28cf339SDave Airlie struct radeon_device *rdev = dev->dev_private; 1759f28cf339SDave Airlie struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1760f28cf339SDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1761f28cf339SDave Airlie struct drm_encoder *test_encoder; 1762f28cf339SDave Airlie struct radeon_encoder_atom_dig *dig; 1763f28cf339SDave Airlie uint32_t dig_enc_in_use = 0; 1764bcc1c2a1SAlex Deucher 1765badbb57bSAlex Deucher /* DCE4/5 */ 1766bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 17675137ee94SAlex Deucher dig = radeon_encoder->enc_priv; 1768cb7cf419SAlex Deucher if (ASIC_IS_DCE41(rdev)) { 17693a6dea31SAlex Deucher /* ontario follows DCE4 */ 17703a6dea31SAlex Deucher if (rdev->family == CHIP_PALM) { 1771cb7cf419SAlex Deucher if (dig->linkb) 1772cb7cf419SAlex Deucher return 1; 1773cb7cf419SAlex Deucher else 1774cb7cf419SAlex Deucher return 0; 17753a6dea31SAlex Deucher } else 17763a6dea31SAlex Deucher /* llano follows DCE3.2 */ 17773a6dea31SAlex Deucher return radeon_crtc->crtc_id; 1778cb7cf419SAlex Deucher } else { 1779bcc1c2a1SAlex Deucher switch (radeon_encoder->encoder_id) { 1780bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 17815137ee94SAlex Deucher if (dig->linkb) 1782bcc1c2a1SAlex Deucher return 1; 1783bcc1c2a1SAlex Deucher else 1784bcc1c2a1SAlex Deucher return 0; 1785bcc1c2a1SAlex Deucher break; 1786bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 17875137ee94SAlex Deucher if (dig->linkb) 1788bcc1c2a1SAlex Deucher return 3; 1789bcc1c2a1SAlex Deucher else 1790bcc1c2a1SAlex Deucher return 2; 1791bcc1c2a1SAlex Deucher break; 1792bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 17935137ee94SAlex Deucher if (dig->linkb) 1794bcc1c2a1SAlex Deucher return 5; 1795bcc1c2a1SAlex Deucher else 1796bcc1c2a1SAlex Deucher return 4; 1797bcc1c2a1SAlex Deucher break; 1798bcc1c2a1SAlex Deucher } 1799bcc1c2a1SAlex Deucher } 1800b61c99deSAlex Deucher } 1801bcc1c2a1SAlex Deucher 1802f28cf339SDave Airlie /* on DCE32 and encoder can driver any block so just crtc id */ 1803f28cf339SDave Airlie if (ASIC_IS_DCE32(rdev)) { 1804f28cf339SDave Airlie return radeon_crtc->crtc_id; 1805f28cf339SDave Airlie } 1806f28cf339SDave Airlie 1807f28cf339SDave Airlie /* on DCE3 - LVTMA can only be driven by DIGB */ 1808f28cf339SDave Airlie list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 1809f28cf339SDave Airlie struct radeon_encoder *radeon_test_encoder; 1810f28cf339SDave Airlie 1811f28cf339SDave Airlie if (encoder == test_encoder) 1812f28cf339SDave Airlie continue; 1813f28cf339SDave Airlie 1814f28cf339SDave Airlie if (!radeon_encoder_is_digital(test_encoder)) 1815f28cf339SDave Airlie continue; 1816f28cf339SDave Airlie 1817f28cf339SDave Airlie radeon_test_encoder = to_radeon_encoder(test_encoder); 1818f28cf339SDave Airlie dig = radeon_test_encoder->enc_priv; 1819f28cf339SDave Airlie 1820f28cf339SDave Airlie if (dig->dig_encoder >= 0) 1821f28cf339SDave Airlie dig_enc_in_use |= (1 << dig->dig_encoder); 1822f28cf339SDave Airlie } 1823f28cf339SDave Airlie 1824f28cf339SDave Airlie if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { 1825f28cf339SDave Airlie if (dig_enc_in_use & 0x2) 1826f28cf339SDave Airlie DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n"); 1827f28cf339SDave Airlie return 1; 1828f28cf339SDave Airlie } 1829f28cf339SDave Airlie if (!(dig_enc_in_use & 1)) 1830f28cf339SDave Airlie return 0; 1831f28cf339SDave Airlie return 1; 1832f28cf339SDave Airlie } 1833f28cf339SDave Airlie 1834ac89af1eSAlex Deucher /* This only needs to be called once at startup */ 1835ac89af1eSAlex Deucher void 1836ac89af1eSAlex Deucher radeon_atom_encoder_init(struct radeon_device *rdev) 1837ac89af1eSAlex Deucher { 1838ac89af1eSAlex Deucher struct drm_device *dev = rdev->ddev; 1839ac89af1eSAlex Deucher struct drm_encoder *encoder; 1840ac89af1eSAlex Deucher 1841ac89af1eSAlex Deucher list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 1842ac89af1eSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1843ac89af1eSAlex Deucher struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); 1844ac89af1eSAlex Deucher 1845ac89af1eSAlex Deucher switch (radeon_encoder->encoder_id) { 1846ac89af1eSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1847ac89af1eSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1848ac89af1eSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1849ac89af1eSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1850ac89af1eSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 1851ac89af1eSAlex Deucher break; 1852ac89af1eSAlex Deucher default: 1853ac89af1eSAlex Deucher break; 1854ac89af1eSAlex Deucher } 1855ac89af1eSAlex Deucher 1856ac89af1eSAlex Deucher if (ext_encoder && ASIC_IS_DCE41(rdev)) 1857ac89af1eSAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 1858ac89af1eSAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); 1859ac89af1eSAlex Deucher } 1860ac89af1eSAlex Deucher } 1861ac89af1eSAlex Deucher 1862771fe6b9SJerome Glisse static void 1863771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder, 1864771fe6b9SJerome Glisse struct drm_display_mode *mode, 1865771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 1866771fe6b9SJerome Glisse { 1867771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1868771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1869771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 18703e4b9982SAlex Deucher struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); 1871771fe6b9SJerome Glisse 1872771fe6b9SJerome Glisse radeon_encoder->pixel_clock = adjusted_mode->clock; 1873771fe6b9SJerome Glisse 1874c6f8505eSAlex Deucher if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { 18754ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1876771fe6b9SJerome Glisse atombios_yuv_setup(encoder, true); 1877771fe6b9SJerome Glisse else 1878771fe6b9SJerome Glisse atombios_yuv_setup(encoder, false); 1879771fe6b9SJerome Glisse } 1880771fe6b9SJerome Glisse 1881771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1882771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1883771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1884771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1885771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1886771fe6b9SJerome Glisse atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 1887771fe6b9SJerome Glisse break; 1888771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1889771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1890771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1891771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1892bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 1893bcc1c2a1SAlex Deucher /* disable the transmitter */ 1894bcc1c2a1SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1895bcc1c2a1SAlex Deucher /* setup and enable the encoder */ 1896558e27dbSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); 1897bcc1c2a1SAlex Deucher 1898ac89af1eSAlex Deucher /* enable the transmitter */ 1899bcc1c2a1SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1900bcc1c2a1SAlex Deucher } else { 1901771fe6b9SJerome Glisse /* disable the encoder and transmitter */ 19021a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1903558e27dbSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); 1904771fe6b9SJerome Glisse 1905771fe6b9SJerome Glisse /* setup and enable the encoder and transmitter */ 1906558e27dbSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); 19071a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 19081a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1909bcc1c2a1SAlex Deucher } 1910771fe6b9SJerome Glisse break; 1911771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1912771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1913771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 191499999aaaSAlex Deucher atombios_dvo_setup(encoder, ATOM_ENABLE); 1915771fe6b9SJerome Glisse break; 1916771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1917771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1918771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1919771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1920771fe6b9SJerome Glisse atombios_dac_setup(encoder, ATOM_ENABLE); 1921d3a67a43SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { 19224ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1923771fe6b9SJerome Glisse atombios_tv_setup(encoder, ATOM_ENABLE); 1924d3a67a43SAlex Deucher else 1925d3a67a43SAlex Deucher atombios_tv_setup(encoder, ATOM_DISABLE); 1926d3a67a43SAlex Deucher } 1927771fe6b9SJerome Glisse break; 1928771fe6b9SJerome Glisse } 19293e4b9982SAlex Deucher 19303e4b9982SAlex Deucher if (ext_encoder) { 1931ac89af1eSAlex Deucher if (ASIC_IS_DCE41(rdev)) 1932bf982ebfSAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 1933bf982ebfSAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 1934ac89af1eSAlex Deucher else 19353e4b9982SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); 19363e4b9982SAlex Deucher } 19373e4b9982SAlex Deucher 1938771fe6b9SJerome Glisse atombios_apply_encoder_quirks(encoder, adjusted_mode); 1939dafc3bd5SChristian Koenig 19402cd6218cSRafał Miłecki if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { 19412cd6218cSRafał Miłecki r600_hdmi_enable(encoder); 1942dafc3bd5SChristian Koenig r600_hdmi_setmode(encoder, adjusted_mode); 1943771fe6b9SJerome Glisse } 19442cd6218cSRafał Miłecki } 1945771fe6b9SJerome Glisse 1946771fe6b9SJerome Glisse static bool 19474ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1948771fe6b9SJerome Glisse { 1949771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1950771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1951771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 19524ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1953771fe6b9SJerome Glisse 1954771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | 1955771fe6b9SJerome Glisse ATOM_DEVICE_CV_SUPPORT | 1956771fe6b9SJerome Glisse ATOM_DEVICE_CRT_SUPPORT)) { 1957771fe6b9SJerome Glisse DAC_LOAD_DETECTION_PS_ALLOCATION args; 1958771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1959771fe6b9SJerome Glisse uint8_t frev, crev; 1960771fe6b9SJerome Glisse 1961771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1962771fe6b9SJerome Glisse 1963a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1964a084e6eeSAlex Deucher return false; 1965771fe6b9SJerome Glisse 1966771fe6b9SJerome Glisse args.sDacload.ucMisc = 0; 1967771fe6b9SJerome Glisse 1968771fe6b9SJerome Glisse if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1969771fe6b9SJerome Glisse (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) 1970771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_A; 1971771fe6b9SJerome Glisse else 1972771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_B; 1973771fe6b9SJerome Glisse 19744ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) 1975771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 19764ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) 1977771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 19784ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1979771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1980771fe6b9SJerome Glisse if (crev >= 3) 1981771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 19824ce001abSDave Airlie } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1983771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1984771fe6b9SJerome Glisse if (crev >= 3) 1985771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1986771fe6b9SJerome Glisse } 1987771fe6b9SJerome Glisse 1988771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1989771fe6b9SJerome Glisse 1990771fe6b9SJerome Glisse return true; 1991771fe6b9SJerome Glisse } else 1992771fe6b9SJerome Glisse return false; 1993771fe6b9SJerome Glisse } 1994771fe6b9SJerome Glisse 1995771fe6b9SJerome Glisse static enum drm_connector_status 1996771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1997771fe6b9SJerome Glisse { 1998771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1999771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 2000771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 20014ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2002771fe6b9SJerome Glisse uint32_t bios_0_scratch; 2003771fe6b9SJerome Glisse 20044ce001abSDave Airlie if (!atombios_dac_load_detect(encoder, connector)) { 2005d9fdaafbSDave Airlie DRM_DEBUG_KMS("detect returned false \n"); 2006771fe6b9SJerome Glisse return connector_status_unknown; 2007771fe6b9SJerome Glisse } 2008771fe6b9SJerome Glisse 2009771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 2010771fe6b9SJerome Glisse bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 2011771fe6b9SJerome Glisse else 2012771fe6b9SJerome Glisse bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 2013771fe6b9SJerome Glisse 2014d9fdaafbSDave Airlie DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 20154ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 2016771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT1_MASK) 2017771fe6b9SJerome Glisse return connector_status_connected; 20184ce001abSDave Airlie } 20194ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 2020771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT2_MASK) 2021771fe6b9SJerome Glisse return connector_status_connected; 20224ce001abSDave Airlie } 20234ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 2024771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 2025771fe6b9SJerome Glisse return connector_status_connected; 20264ce001abSDave Airlie } 20274ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 2028771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 2029771fe6b9SJerome Glisse return connector_status_connected; /* CTV */ 2030771fe6b9SJerome Glisse else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 2031771fe6b9SJerome Glisse return connector_status_connected; /* STV */ 2032771fe6b9SJerome Glisse } 2033771fe6b9SJerome Glisse return connector_status_disconnected; 2034771fe6b9SJerome Glisse } 2035771fe6b9SJerome Glisse 2036d629a3ceSAlex Deucher static enum drm_connector_status 2037d629a3ceSAlex Deucher radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) 2038d629a3ceSAlex Deucher { 2039d629a3ceSAlex Deucher struct drm_device *dev = encoder->dev; 2040d629a3ceSAlex Deucher struct radeon_device *rdev = dev->dev_private; 2041d629a3ceSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2042d629a3ceSAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2043d629a3ceSAlex Deucher struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); 2044d629a3ceSAlex Deucher u32 bios_0_scratch; 2045d629a3ceSAlex Deucher 2046d629a3ceSAlex Deucher if (!ASIC_IS_DCE4(rdev)) 2047d629a3ceSAlex Deucher return connector_status_unknown; 2048d629a3ceSAlex Deucher 2049d629a3ceSAlex Deucher if (!ext_encoder) 2050d629a3ceSAlex Deucher return connector_status_unknown; 2051d629a3ceSAlex Deucher 2052d629a3ceSAlex Deucher if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) 2053d629a3ceSAlex Deucher return connector_status_unknown; 2054d629a3ceSAlex Deucher 2055d629a3ceSAlex Deucher /* load detect on the dp bridge */ 2056d629a3ceSAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 2057d629a3ceSAlex Deucher EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); 2058d629a3ceSAlex Deucher 2059d629a3ceSAlex Deucher bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 2060d629a3ceSAlex Deucher 2061d629a3ceSAlex Deucher DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 2062d629a3ceSAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 2063d629a3ceSAlex Deucher if (bios_0_scratch & ATOM_S0_CRT1_MASK) 2064d629a3ceSAlex Deucher return connector_status_connected; 2065d629a3ceSAlex Deucher } 2066d629a3ceSAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 2067d629a3ceSAlex Deucher if (bios_0_scratch & ATOM_S0_CRT2_MASK) 2068d629a3ceSAlex Deucher return connector_status_connected; 2069d629a3ceSAlex Deucher } 2070d629a3ceSAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 2071d629a3ceSAlex Deucher if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 2072d629a3ceSAlex Deucher return connector_status_connected; 2073d629a3ceSAlex Deucher } 2074d629a3ceSAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 2075d629a3ceSAlex Deucher if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 2076d629a3ceSAlex Deucher return connector_status_connected; /* CTV */ 2077d629a3ceSAlex Deucher else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 2078d629a3ceSAlex Deucher return connector_status_connected; /* STV */ 2079d629a3ceSAlex Deucher } 2080d629a3ceSAlex Deucher return connector_status_disconnected; 2081d629a3ceSAlex Deucher } 2082d629a3ceSAlex Deucher 2083591a10e1SAlex Deucher void 2084591a10e1SAlex Deucher radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) 2085591a10e1SAlex Deucher { 2086591a10e1SAlex Deucher struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); 2087591a10e1SAlex Deucher 2088591a10e1SAlex Deucher if (ext_encoder) 2089591a10e1SAlex Deucher /* ddc_setup on the dp bridge */ 2090591a10e1SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 2091591a10e1SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); 2092591a10e1SAlex Deucher 2093591a10e1SAlex Deucher } 2094591a10e1SAlex Deucher 2095771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) 2096771fe6b9SJerome Glisse { 2097267364acSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2098fb939dfcSAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 2099267364acSAlex Deucher 2100eac4dff6SAlex Deucher if ((radeon_encoder->active_device & 2101eac4dff6SAlex Deucher (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || 2102*1d33e1fcSAlex Deucher (radeon_encoder_get_dp_bridge_encoder_id(encoder) != 2103*1d33e1fcSAlex Deucher ENCODER_OBJECT_ID_NONE)) { 2104267364acSAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 2105267364acSAlex Deucher if (dig) 2106267364acSAlex Deucher dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); 2107267364acSAlex Deucher } 2108267364acSAlex Deucher 2109771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, true); 2110771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 2111267364acSAlex Deucher 2112fb939dfcSAlex Deucher if (connector) { 2113fb939dfcSAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 21144e633939SAlex Deucher 21154e633939SAlex Deucher /* select the clock/data port if it uses a router */ 2116fb939dfcSAlex Deucher if (radeon_connector->router.cd_valid) 2117fb939dfcSAlex Deucher radeon_router_select_cd_port(radeon_connector); 21184e633939SAlex Deucher 21194e633939SAlex Deucher /* turn eDP panel on for mode set */ 21204e633939SAlex Deucher if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) 21214e633939SAlex Deucher atombios_set_edp_panel_power(connector, 21224e633939SAlex Deucher ATOM_TRANSMITTER_ACTION_POWER_ON); 2123fb939dfcSAlex Deucher } 2124fb939dfcSAlex Deucher 2125267364acSAlex Deucher /* this is needed for the pll/ss setup to work correctly in some cases */ 2126267364acSAlex Deucher atombios_set_encoder_crtc_source(encoder); 2127771fe6b9SJerome Glisse } 2128771fe6b9SJerome Glisse 2129771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder) 2130771fe6b9SJerome Glisse { 2131771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 2132771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, false); 2133771fe6b9SJerome Glisse } 2134771fe6b9SJerome Glisse 21354ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder) 21364ce001abSDave Airlie { 2137aa961391SAlex Deucher struct drm_device *dev = encoder->dev; 2138aa961391SAlex Deucher struct radeon_device *rdev = dev->dev_private; 21394ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2140f28cf339SDave Airlie struct radeon_encoder_atom_dig *dig; 2141a0ae5864SAlex Deucher 2142a0ae5864SAlex Deucher /* check for pre-DCE3 cards with shared encoders; 2143a0ae5864SAlex Deucher * can't really use the links individually, so don't disable 2144a0ae5864SAlex Deucher * the encoder if it's in use by another connector 2145a0ae5864SAlex Deucher */ 2146a0ae5864SAlex Deucher if (!ASIC_IS_DCE3(rdev)) { 2147a0ae5864SAlex Deucher struct drm_encoder *other_encoder; 2148a0ae5864SAlex Deucher struct radeon_encoder *other_radeon_encoder; 2149a0ae5864SAlex Deucher 2150a0ae5864SAlex Deucher list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { 2151a0ae5864SAlex Deucher other_radeon_encoder = to_radeon_encoder(other_encoder); 2152a0ae5864SAlex Deucher if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && 2153a0ae5864SAlex Deucher drm_helper_encoder_in_use(other_encoder)) 2154a0ae5864SAlex Deucher goto disable_done; 2155a0ae5864SAlex Deucher } 2156a0ae5864SAlex Deucher } 2157a0ae5864SAlex Deucher 21584ce001abSDave Airlie radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 2159f28cf339SDave Airlie 2160aa961391SAlex Deucher switch (radeon_encoder->encoder_id) { 2161aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2162aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2163aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2164aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2165aa961391SAlex Deucher atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE); 2166aa961391SAlex Deucher break; 2167aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2168aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2169aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2170aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2171aa961391SAlex Deucher if (ASIC_IS_DCE4(rdev)) 2172aa961391SAlex Deucher /* disable the transmitter */ 2173aa961391SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 2174aa961391SAlex Deucher else { 2175aa961391SAlex Deucher /* disable the encoder and transmitter */ 2176aa961391SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 2177558e27dbSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); 2178aa961391SAlex Deucher } 2179aa961391SAlex Deucher break; 2180aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 2181aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2182aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 218399999aaaSAlex Deucher atombios_dvo_setup(encoder, ATOM_DISABLE); 2184aa961391SAlex Deucher break; 2185aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2186aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2187aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2188aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2189aa961391SAlex Deucher atombios_dac_setup(encoder, ATOM_DISABLE); 21908bf3aae6SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 2191aa961391SAlex Deucher atombios_tv_setup(encoder, ATOM_DISABLE); 2192aa961391SAlex Deucher break; 2193aa961391SAlex Deucher } 2194aa961391SAlex Deucher 2195a0ae5864SAlex Deucher disable_done: 2196f28cf339SDave Airlie if (radeon_encoder_is_digital(encoder)) { 21972cd6218cSRafał Miłecki if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 21982cd6218cSRafał Miłecki r600_hdmi_disable(encoder); 2199f28cf339SDave Airlie dig = radeon_encoder->enc_priv; 2200f28cf339SDave Airlie dig->dig_encoder = -1; 2201f28cf339SDave Airlie } 22024ce001abSDave Airlie radeon_encoder->active_device = 0; 22034ce001abSDave Airlie } 22044ce001abSDave Airlie 22053e4b9982SAlex Deucher /* these are handled by the primary encoders */ 22063e4b9982SAlex Deucher static void radeon_atom_ext_prepare(struct drm_encoder *encoder) 22073e4b9982SAlex Deucher { 22083e4b9982SAlex Deucher 22093e4b9982SAlex Deucher } 22103e4b9982SAlex Deucher 22113e4b9982SAlex Deucher static void radeon_atom_ext_commit(struct drm_encoder *encoder) 22123e4b9982SAlex Deucher { 22133e4b9982SAlex Deucher 22143e4b9982SAlex Deucher } 22153e4b9982SAlex Deucher 22163e4b9982SAlex Deucher static void 22173e4b9982SAlex Deucher radeon_atom_ext_mode_set(struct drm_encoder *encoder, 22183e4b9982SAlex Deucher struct drm_display_mode *mode, 22193e4b9982SAlex Deucher struct drm_display_mode *adjusted_mode) 22203e4b9982SAlex Deucher { 22213e4b9982SAlex Deucher 22223e4b9982SAlex Deucher } 22233e4b9982SAlex Deucher 22243e4b9982SAlex Deucher static void radeon_atom_ext_disable(struct drm_encoder *encoder) 22253e4b9982SAlex Deucher { 22263e4b9982SAlex Deucher 22273e4b9982SAlex Deucher } 22283e4b9982SAlex Deucher 22293e4b9982SAlex Deucher static void 22303e4b9982SAlex Deucher radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) 22313e4b9982SAlex Deucher { 22323e4b9982SAlex Deucher 22333e4b9982SAlex Deucher } 22343e4b9982SAlex Deucher 22353e4b9982SAlex Deucher static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, 22363e4b9982SAlex Deucher struct drm_display_mode *mode, 22373e4b9982SAlex Deucher struct drm_display_mode *adjusted_mode) 22383e4b9982SAlex Deucher { 22393e4b9982SAlex Deucher return true; 22403e4b9982SAlex Deucher } 22413e4b9982SAlex Deucher 22423e4b9982SAlex Deucher static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { 22433e4b9982SAlex Deucher .dpms = radeon_atom_ext_dpms, 22443e4b9982SAlex Deucher .mode_fixup = radeon_atom_ext_mode_fixup, 22453e4b9982SAlex Deucher .prepare = radeon_atom_ext_prepare, 22463e4b9982SAlex Deucher .mode_set = radeon_atom_ext_mode_set, 22473e4b9982SAlex Deucher .commit = radeon_atom_ext_commit, 22483e4b9982SAlex Deucher .disable = radeon_atom_ext_disable, 22493e4b9982SAlex Deucher /* no detect for TMDS/LVDS yet */ 22503e4b9982SAlex Deucher }; 22513e4b9982SAlex Deucher 2252771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 2253771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 2254771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 2255771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 2256771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 2257771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 22584ce001abSDave Airlie .disable = radeon_atom_encoder_disable, 2259d629a3ceSAlex Deucher .detect = radeon_atom_dig_detect, 2260771fe6b9SJerome Glisse }; 2261771fe6b9SJerome Glisse 2262771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { 2263771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 2264771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 2265771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 2266771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 2267771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 2268771fe6b9SJerome Glisse .detect = radeon_atom_dac_detect, 2269771fe6b9SJerome Glisse }; 2270771fe6b9SJerome Glisse 2271771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder) 2272771fe6b9SJerome Glisse { 2273771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2274771fe6b9SJerome Glisse kfree(radeon_encoder->enc_priv); 2275771fe6b9SJerome Glisse drm_encoder_cleanup(encoder); 2276771fe6b9SJerome Glisse kfree(radeon_encoder); 2277771fe6b9SJerome Glisse } 2278771fe6b9SJerome Glisse 2279771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = { 2280771fe6b9SJerome Glisse .destroy = radeon_enc_destroy, 2281771fe6b9SJerome Glisse }; 2282771fe6b9SJerome Glisse 22834ce001abSDave Airlie struct radeon_encoder_atom_dac * 22844ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) 22854ce001abSDave Airlie { 2286affd8589SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 2287affd8589SAlex Deucher struct radeon_device *rdev = dev->dev_private; 22884ce001abSDave Airlie struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); 22894ce001abSDave Airlie 22904ce001abSDave Airlie if (!dac) 22914ce001abSDave Airlie return NULL; 22924ce001abSDave Airlie 2293affd8589SAlex Deucher dac->tv_std = radeon_atombios_get_tv_info(rdev); 22944ce001abSDave Airlie return dac; 22954ce001abSDave Airlie } 22964ce001abSDave Airlie 2297771fe6b9SJerome Glisse struct radeon_encoder_atom_dig * 2298771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) 2299771fe6b9SJerome Glisse { 23005137ee94SAlex Deucher int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 2301771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); 2302771fe6b9SJerome Glisse 2303771fe6b9SJerome Glisse if (!dig) 2304771fe6b9SJerome Glisse return NULL; 2305771fe6b9SJerome Glisse 2306771fe6b9SJerome Glisse /* coherent mode by default */ 2307771fe6b9SJerome Glisse dig->coherent_mode = true; 2308f28cf339SDave Airlie dig->dig_encoder = -1; 2309771fe6b9SJerome Glisse 23105137ee94SAlex Deucher if (encoder_enum == 2) 23115137ee94SAlex Deucher dig->linkb = true; 23125137ee94SAlex Deucher else 23135137ee94SAlex Deucher dig->linkb = false; 23145137ee94SAlex Deucher 2315771fe6b9SJerome Glisse return dig; 2316771fe6b9SJerome Glisse } 2317771fe6b9SJerome Glisse 2318771fe6b9SJerome Glisse void 231936868bdaSAlex Deucher radeon_add_atom_encoder(struct drm_device *dev, 232036868bdaSAlex Deucher uint32_t encoder_enum, 232136868bdaSAlex Deucher uint32_t supported_device, 232236868bdaSAlex Deucher u16 caps) 2323771fe6b9SJerome Glisse { 2324dfee5614SDave Airlie struct radeon_device *rdev = dev->dev_private; 2325771fe6b9SJerome Glisse struct drm_encoder *encoder; 2326771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 2327771fe6b9SJerome Glisse 2328771fe6b9SJerome Glisse /* see if we already added it */ 2329771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 2330771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 23315137ee94SAlex Deucher if (radeon_encoder->encoder_enum == encoder_enum) { 2332771fe6b9SJerome Glisse radeon_encoder->devices |= supported_device; 2333771fe6b9SJerome Glisse return; 2334771fe6b9SJerome Glisse } 2335771fe6b9SJerome Glisse 2336771fe6b9SJerome Glisse } 2337771fe6b9SJerome Glisse 2338771fe6b9SJerome Glisse /* add a new one */ 2339771fe6b9SJerome Glisse radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); 2340771fe6b9SJerome Glisse if (!radeon_encoder) 2341771fe6b9SJerome Glisse return; 2342771fe6b9SJerome Glisse 2343771fe6b9SJerome Glisse encoder = &radeon_encoder->base; 2344bcc1c2a1SAlex Deucher switch (rdev->num_crtc) { 2345bcc1c2a1SAlex Deucher case 1: 2346dfee5614SDave Airlie encoder->possible_crtcs = 0x1; 2347bcc1c2a1SAlex Deucher break; 2348bcc1c2a1SAlex Deucher case 2: 2349bcc1c2a1SAlex Deucher default: 2350771fe6b9SJerome Glisse encoder->possible_crtcs = 0x3; 2351bcc1c2a1SAlex Deucher break; 235233ae1827SAlex Deucher case 4: 235333ae1827SAlex Deucher encoder->possible_crtcs = 0xf; 235433ae1827SAlex Deucher break; 2355bcc1c2a1SAlex Deucher case 6: 2356bcc1c2a1SAlex Deucher encoder->possible_crtcs = 0x3f; 2357bcc1c2a1SAlex Deucher break; 2358bcc1c2a1SAlex Deucher } 2359771fe6b9SJerome Glisse 2360771fe6b9SJerome Glisse radeon_encoder->enc_priv = NULL; 2361771fe6b9SJerome Glisse 23625137ee94SAlex Deucher radeon_encoder->encoder_enum = encoder_enum; 23635137ee94SAlex Deucher radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 2364771fe6b9SJerome Glisse radeon_encoder->devices = supported_device; 2365c93bb85bSJerome Glisse radeon_encoder->rmx_type = RMX_OFF; 23665b1714d3SAlex Deucher radeon_encoder->underscan_type = UNDERSCAN_OFF; 23673e4b9982SAlex Deucher radeon_encoder->is_ext_encoder = false; 236836868bdaSAlex Deucher radeon_encoder->caps = caps; 2369771fe6b9SJerome Glisse 2370771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 2371771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2372771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2373771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2374771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2375771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 2376771fe6b9SJerome Glisse radeon_encoder->rmx_type = RMX_FULL; 2377771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 2378771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 2379771fe6b9SJerome Glisse } else { 2380771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 2381771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 2382771fe6b9SJerome Glisse } 2383771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 2384771fe6b9SJerome Glisse break; 2385771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2386771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 2387affd8589SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 2388771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 2389771fe6b9SJerome Glisse break; 2390771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2391771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2392771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2393771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); 23944ce001abSDave Airlie radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 2395771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 2396771fe6b9SJerome Glisse break; 2397771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2398771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 2399771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 2400771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2401771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2402771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2403771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 240460d15f55SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 240560d15f55SAlex Deucher radeon_encoder->rmx_type = RMX_FULL; 240660d15f55SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 240760d15f55SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 24083e4b9982SAlex Deucher } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { 24093e4b9982SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 24103e4b9982SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 241160d15f55SAlex Deucher } else { 2412771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 2413771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 241460d15f55SAlex Deucher } 2415771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 2416771fe6b9SJerome Glisse break; 24173e4b9982SAlex Deucher case ENCODER_OBJECT_ID_SI170B: 24183e4b9982SAlex Deucher case ENCODER_OBJECT_ID_CH7303: 24193e4b9982SAlex Deucher case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 24203e4b9982SAlex Deucher case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 24213e4b9982SAlex Deucher case ENCODER_OBJECT_ID_TITFP513: 24223e4b9982SAlex Deucher case ENCODER_OBJECT_ID_VT1623: 24233e4b9982SAlex Deucher case ENCODER_OBJECT_ID_HDMI_SI1930: 2424bf982ebfSAlex Deucher case ENCODER_OBJECT_ID_TRAVIS: 2425bf982ebfSAlex Deucher case ENCODER_OBJECT_ID_NUTMEG: 24263e4b9982SAlex Deucher /* these are handled by the primary encoders */ 24273e4b9982SAlex Deucher radeon_encoder->is_ext_encoder = true; 24283e4b9982SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 24293e4b9982SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 24303e4b9982SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) 24313e4b9982SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 24323e4b9982SAlex Deucher else 24333e4b9982SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 24343e4b9982SAlex Deucher drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs); 24353e4b9982SAlex Deucher break; 2436771fe6b9SJerome Glisse } 2437771fe6b9SJerome Glisse } 2438