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 84771fe6b9SJerome Glisse radeon_get_encoder_id(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)) 100771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 101771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 102771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 103771fe6b9SJerome Glisse else 104771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 105771fe6b9SJerome Glisse break; 106771fe6b9SJerome Glisse case 2: /* dac b */ 107771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 108771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 109771fe6b9SJerome Glisse else { 110771fe6b9SJerome Glisse /*if (rdev->family == CHIP_R200) 111771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 112771fe6b9SJerome Glisse else*/ 113771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 114771fe6b9SJerome Glisse } 115771fe6b9SJerome Glisse break; 116771fe6b9SJerome Glisse case 3: /* external dac */ 117771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 118771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 119771fe6b9SJerome Glisse else 120771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 121771fe6b9SJerome Glisse break; 122771fe6b9SJerome Glisse } 123771fe6b9SJerome Glisse break; 124771fe6b9SJerome Glisse case ATOM_DEVICE_LCD1_SUPPORT: 125771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 126771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 127771fe6b9SJerome Glisse else 128771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 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)) 134771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 135771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 136771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 137771fe6b9SJerome Glisse else 138771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 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)) 145771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 146771fe6b9SJerome Glisse else if (ASIC_IS_AVIVO(rdev)) 147771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 148771fe6b9SJerome Glisse else 149771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 150771fe6b9SJerome Glisse break; 151771fe6b9SJerome Glisse case ATOM_DEVICE_DFP3_SUPPORT: 152771fe6b9SJerome Glisse ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 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 } 179771fe6b9SJerome Glisse void 180771fe6b9SJerome Glisse radeon_link_encoder_connector(struct drm_device *dev) 181771fe6b9SJerome Glisse { 182771fe6b9SJerome Glisse struct drm_connector *connector; 183771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 184771fe6b9SJerome Glisse struct drm_encoder *encoder; 185771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 186771fe6b9SJerome Glisse 187771fe6b9SJerome Glisse /* walk the list and link encoders to connectors */ 188771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 189771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 190771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 191771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 192771fe6b9SJerome Glisse if (radeon_encoder->devices & radeon_connector->devices) 193771fe6b9SJerome Glisse drm_mode_connector_attach_encoder(connector, encoder); 194771fe6b9SJerome Glisse } 195771fe6b9SJerome Glisse } 196771fe6b9SJerome Glisse } 197771fe6b9SJerome Glisse 1984ce001abSDave Airlie void radeon_encoder_set_active_device(struct drm_encoder *encoder) 1994ce001abSDave Airlie { 2004ce001abSDave Airlie struct drm_device *dev = encoder->dev; 2014ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2024ce001abSDave Airlie struct drm_connector *connector; 2034ce001abSDave Airlie 2044ce001abSDave Airlie list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2054ce001abSDave Airlie if (connector->encoder == encoder) { 2064ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 2074ce001abSDave Airlie radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; 208*d9fdaafbSDave Airlie DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n", 2094ce001abSDave Airlie radeon_encoder->active_device, radeon_encoder->devices, 2104ce001abSDave Airlie radeon_connector->devices, encoder->encoder_type); 2114ce001abSDave Airlie } 2124ce001abSDave Airlie } 2134ce001abSDave Airlie } 2144ce001abSDave Airlie 215771fe6b9SJerome Glisse static struct drm_connector * 216771fe6b9SJerome Glisse radeon_get_connector_for_encoder(struct drm_encoder *encoder) 217771fe6b9SJerome Glisse { 218771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 219771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 220771fe6b9SJerome Glisse struct drm_connector *connector; 221771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 222771fe6b9SJerome Glisse 223771fe6b9SJerome Glisse list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 224771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 22543c33ed8SDave Airlie if (radeon_encoder->active_device & radeon_connector->devices) 226771fe6b9SJerome Glisse return connector; 227771fe6b9SJerome Glisse } 228771fe6b9SJerome Glisse return NULL; 229771fe6b9SJerome Glisse } 230771fe6b9SJerome Glisse 2319ae47867SAlex Deucher static struct radeon_connector_atom_dig * 2329ae47867SAlex Deucher radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder) 2339ae47867SAlex Deucher { 2349ae47867SAlex Deucher struct drm_device *dev = encoder->dev; 2359ae47867SAlex Deucher struct radeon_device *rdev = dev->dev_private; 2369ae47867SAlex Deucher struct drm_connector *connector; 2379ae47867SAlex Deucher struct radeon_connector *radeon_connector; 2389ae47867SAlex Deucher struct radeon_connector_atom_dig *dig_connector; 2399ae47867SAlex Deucher 2409ae47867SAlex Deucher if (!rdev->is_atom_bios) 2419ae47867SAlex Deucher return NULL; 2429ae47867SAlex Deucher 2439ae47867SAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 2449ae47867SAlex Deucher if (!connector) 2459ae47867SAlex Deucher return NULL; 2469ae47867SAlex Deucher 2479ae47867SAlex Deucher radeon_connector = to_radeon_connector(connector); 2489ae47867SAlex Deucher 2499ae47867SAlex Deucher if (!radeon_connector->con_priv) 2509ae47867SAlex Deucher return NULL; 2519ae47867SAlex Deucher 2529ae47867SAlex Deucher dig_connector = radeon_connector->con_priv; 2539ae47867SAlex Deucher 2549ae47867SAlex Deucher return dig_connector; 2559ae47867SAlex Deucher } 2569ae47867SAlex Deucher 2573515387bSAlex Deucher void radeon_panel_mode_fixup(struct drm_encoder *encoder, 2583515387bSAlex Deucher struct drm_display_mode *adjusted_mode) 2593515387bSAlex Deucher { 2603515387bSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2613515387bSAlex Deucher struct drm_device *dev = encoder->dev; 2623515387bSAlex Deucher struct radeon_device *rdev = dev->dev_private; 2633515387bSAlex Deucher struct drm_display_mode *native_mode = &radeon_encoder->native_mode; 2643515387bSAlex Deucher unsigned hblank = native_mode->htotal - native_mode->hdisplay; 2653515387bSAlex Deucher unsigned vblank = native_mode->vtotal - native_mode->vdisplay; 2663515387bSAlex Deucher unsigned hover = native_mode->hsync_start - native_mode->hdisplay; 2673515387bSAlex Deucher unsigned vover = native_mode->vsync_start - native_mode->vdisplay; 2683515387bSAlex Deucher unsigned hsync_width = native_mode->hsync_end - native_mode->hsync_start; 2693515387bSAlex Deucher unsigned vsync_width = native_mode->vsync_end - native_mode->vsync_start; 2703515387bSAlex Deucher 2713515387bSAlex Deucher adjusted_mode->clock = native_mode->clock; 2723515387bSAlex Deucher adjusted_mode->flags = native_mode->flags; 2733515387bSAlex Deucher 2743515387bSAlex Deucher if (ASIC_IS_AVIVO(rdev)) { 2753515387bSAlex Deucher adjusted_mode->hdisplay = native_mode->hdisplay; 2763515387bSAlex Deucher adjusted_mode->vdisplay = native_mode->vdisplay; 2773515387bSAlex Deucher } 2783515387bSAlex Deucher 2793515387bSAlex Deucher adjusted_mode->htotal = native_mode->hdisplay + hblank; 2803515387bSAlex Deucher adjusted_mode->hsync_start = native_mode->hdisplay + hover; 2813515387bSAlex Deucher adjusted_mode->hsync_end = adjusted_mode->hsync_start + hsync_width; 2823515387bSAlex Deucher 2833515387bSAlex Deucher adjusted_mode->vtotal = native_mode->vdisplay + vblank; 2843515387bSAlex Deucher adjusted_mode->vsync_start = native_mode->vdisplay + vover; 2853515387bSAlex Deucher adjusted_mode->vsync_end = adjusted_mode->vsync_start + vsync_width; 2863515387bSAlex Deucher 2873515387bSAlex Deucher drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); 2883515387bSAlex Deucher 2893515387bSAlex Deucher if (ASIC_IS_AVIVO(rdev)) { 2903515387bSAlex Deucher adjusted_mode->crtc_hdisplay = native_mode->hdisplay; 2913515387bSAlex Deucher adjusted_mode->crtc_vdisplay = native_mode->vdisplay; 2923515387bSAlex Deucher } 2933515387bSAlex Deucher 2943515387bSAlex Deucher adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + hblank; 2953515387bSAlex Deucher adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + hover; 2963515387bSAlex Deucher adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + hsync_width; 2973515387bSAlex Deucher 2983515387bSAlex Deucher adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + vblank; 2993515387bSAlex Deucher adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + vover; 3003515387bSAlex Deucher adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + vsync_width; 3013515387bSAlex Deucher 3023515387bSAlex Deucher } 3033515387bSAlex Deucher 304771fe6b9SJerome Glisse static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, 305771fe6b9SJerome Glisse struct drm_display_mode *mode, 306771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 307771fe6b9SJerome Glisse { 308771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 3095a9bcaccSAlex Deucher struct drm_device *dev = encoder->dev; 3105a9bcaccSAlex Deucher struct radeon_device *rdev = dev->dev_private; 311771fe6b9SJerome Glisse 3128c2a6d73SAlex Deucher /* set the active encoder to connector routing */ 3138c2a6d73SAlex Deucher radeon_encoder_set_active_device(encoder); 314771fe6b9SJerome Glisse drm_mode_set_crtcinfo(adjusted_mode, 0); 315771fe6b9SJerome Glisse 316771fe6b9SJerome Glisse /* hw bug */ 317771fe6b9SJerome Glisse if ((mode->flags & DRM_MODE_FLAG_INTERLACE) 318771fe6b9SJerome Glisse && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) 319771fe6b9SJerome Glisse adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; 320771fe6b9SJerome Glisse 32180297e87SAlex Deucher /* get the native mode for LVDS */ 3223515387bSAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 3233515387bSAlex Deucher radeon_panel_mode_fixup(encoder, adjusted_mode); 32480297e87SAlex Deucher 32580297e87SAlex Deucher /* get the native mode for TV */ 326ceefedd8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 3275a9bcaccSAlex Deucher struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; 3285a9bcaccSAlex Deucher if (tv_dac) { 3295a9bcaccSAlex Deucher if (tv_dac->tv_std == TV_STD_NTSC || 3305a9bcaccSAlex Deucher tv_dac->tv_std == TV_STD_NTSC_J || 3315a9bcaccSAlex Deucher tv_dac->tv_std == TV_STD_PAL_M) 3325a9bcaccSAlex Deucher radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); 3335a9bcaccSAlex Deucher else 3345a9bcaccSAlex Deucher radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); 3355a9bcaccSAlex Deucher } 3365a9bcaccSAlex Deucher } 3375a9bcaccSAlex Deucher 3385801ead6SAlex Deucher if (ASIC_IS_DCE3(rdev) && 3399f998ad7SAlex Deucher (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { 3405801ead6SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 3415801ead6SAlex Deucher radeon_dp_set_link_config(connector, mode); 3425801ead6SAlex Deucher } 3435801ead6SAlex Deucher 344771fe6b9SJerome Glisse return true; 345771fe6b9SJerome Glisse } 346771fe6b9SJerome Glisse 347771fe6b9SJerome Glisse static void 348771fe6b9SJerome Glisse atombios_dac_setup(struct drm_encoder *encoder, int action) 349771fe6b9SJerome Glisse { 350771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 351771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 352771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 353771fe6b9SJerome Glisse DAC_ENCODER_CONTROL_PS_ALLOCATION args; 354affd8589SAlex Deucher int index = 0; 355445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 356445282dbSDave Airlie 357771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 358771fe6b9SJerome Glisse 359771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 360771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 361771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 362771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 363771fe6b9SJerome Glisse break; 364771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 365771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 366771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 367771fe6b9SJerome Glisse break; 368771fe6b9SJerome Glisse } 369771fe6b9SJerome Glisse 370771fe6b9SJerome Glisse args.ucAction = action; 371771fe6b9SJerome Glisse 3724ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 373771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PS2; 3744ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 375771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_CV; 376771fe6b9SJerome Glisse else { 377affd8589SAlex Deucher switch (dac_info->tv_std) { 378771fe6b9SJerome Glisse case TV_STD_PAL: 379771fe6b9SJerome Glisse case TV_STD_PAL_M: 380771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 381771fe6b9SJerome Glisse case TV_STD_SECAM: 382771fe6b9SJerome Glisse case TV_STD_PAL_CN: 383771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_PAL; 384771fe6b9SJerome Glisse break; 385771fe6b9SJerome Glisse case TV_STD_NTSC: 386771fe6b9SJerome Glisse case TV_STD_NTSC_J: 387771fe6b9SJerome Glisse case TV_STD_PAL_60: 388771fe6b9SJerome Glisse default: 389771fe6b9SJerome Glisse args.ucDacStandard = ATOM_DAC1_NTSC; 390771fe6b9SJerome Glisse break; 391771fe6b9SJerome Glisse } 392771fe6b9SJerome Glisse } 393771fe6b9SJerome Glisse args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 394771fe6b9SJerome Glisse 395771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 396771fe6b9SJerome Glisse 397771fe6b9SJerome Glisse } 398771fe6b9SJerome Glisse 399771fe6b9SJerome Glisse static void 400771fe6b9SJerome Glisse atombios_tv_setup(struct drm_encoder *encoder, int action) 401771fe6b9SJerome Glisse { 402771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 403771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 404771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 405771fe6b9SJerome Glisse TV_ENCODER_CONTROL_PS_ALLOCATION args; 406771fe6b9SJerome Glisse int index = 0; 407445282dbSDave Airlie struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 408445282dbSDave Airlie 409771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 410771fe6b9SJerome Glisse 411771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 412771fe6b9SJerome Glisse 413771fe6b9SJerome Glisse args.sTVEncoder.ucAction = action; 414771fe6b9SJerome Glisse 4154ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 416771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 417771fe6b9SJerome Glisse else { 418affd8589SAlex Deucher switch (dac_info->tv_std) { 419771fe6b9SJerome Glisse case TV_STD_NTSC: 420771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 421771fe6b9SJerome Glisse break; 422771fe6b9SJerome Glisse case TV_STD_PAL: 423771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 424771fe6b9SJerome Glisse break; 425771fe6b9SJerome Glisse case TV_STD_PAL_M: 426771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 427771fe6b9SJerome Glisse break; 428771fe6b9SJerome Glisse case TV_STD_PAL_60: 429771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 430771fe6b9SJerome Glisse break; 431771fe6b9SJerome Glisse case TV_STD_NTSC_J: 432771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 433771fe6b9SJerome Glisse break; 434771fe6b9SJerome Glisse case TV_STD_SCART_PAL: 435771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 436771fe6b9SJerome Glisse break; 437771fe6b9SJerome Glisse case TV_STD_SECAM: 438771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 439771fe6b9SJerome Glisse break; 440771fe6b9SJerome Glisse case TV_STD_PAL_CN: 441771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 442771fe6b9SJerome Glisse break; 443771fe6b9SJerome Glisse default: 444771fe6b9SJerome Glisse args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 445771fe6b9SJerome Glisse break; 446771fe6b9SJerome Glisse } 447771fe6b9SJerome Glisse } 448771fe6b9SJerome Glisse 449771fe6b9SJerome Glisse args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 450771fe6b9SJerome Glisse 451771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 452771fe6b9SJerome Glisse 453771fe6b9SJerome Glisse } 454771fe6b9SJerome Glisse 455771fe6b9SJerome Glisse void 456771fe6b9SJerome Glisse atombios_external_tmds_setup(struct drm_encoder *encoder, int action) 457771fe6b9SJerome Glisse { 458771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 459771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 460771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 461771fe6b9SJerome Glisse ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args; 462771fe6b9SJerome Glisse int index = 0; 463771fe6b9SJerome Glisse 464771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 465771fe6b9SJerome Glisse 466771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 467771fe6b9SJerome Glisse 468771fe6b9SJerome Glisse args.sXTmdsEncoder.ucEnable = action; 469771fe6b9SJerome Glisse 470771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 471771fe6b9SJerome Glisse args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; 472771fe6b9SJerome Glisse 473771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8)*/ 474771fe6b9SJerome Glisse args.sXTmdsEncoder.ucMisc |= (1 << 1); 475771fe6b9SJerome Glisse 476771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 477771fe6b9SJerome Glisse 478771fe6b9SJerome Glisse } 479771fe6b9SJerome Glisse 480771fe6b9SJerome Glisse static void 481771fe6b9SJerome Glisse atombios_ddia_setup(struct drm_encoder *encoder, int action) 482771fe6b9SJerome Glisse { 483771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 484771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 485771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 486771fe6b9SJerome Glisse DVO_ENCODER_CONTROL_PS_ALLOCATION args; 487771fe6b9SJerome Glisse int index = 0; 488771fe6b9SJerome Glisse 489771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 490771fe6b9SJerome Glisse 491771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 492771fe6b9SJerome Glisse 493771fe6b9SJerome Glisse args.sDVOEncoder.ucAction = action; 494771fe6b9SJerome Glisse args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 495771fe6b9SJerome Glisse 496771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 497771fe6b9SJerome Glisse args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; 498771fe6b9SJerome Glisse 499771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 500771fe6b9SJerome Glisse 501771fe6b9SJerome Glisse } 502771fe6b9SJerome Glisse 503771fe6b9SJerome Glisse union lvds_encoder_control { 504771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 505771fe6b9SJerome Glisse LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 506771fe6b9SJerome Glisse }; 507771fe6b9SJerome Glisse 50832f48ffeSAlex Deucher void 509771fe6b9SJerome Glisse atombios_digital_setup(struct drm_encoder *encoder, int action) 510771fe6b9SJerome Glisse { 511771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 512771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 513771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 5149ae47867SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 5159ae47867SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 5169ae47867SAlex Deucher radeon_get_atom_connector_priv_from_encoder(encoder); 517771fe6b9SJerome Glisse union lvds_encoder_control args; 518771fe6b9SJerome Glisse int index = 0; 519dafc3bd5SChristian Koenig int hdmi_detected = 0; 520771fe6b9SJerome Glisse uint8_t frev, crev; 521771fe6b9SJerome Glisse 5229ae47867SAlex Deucher if (!dig || !dig_connector) 523771fe6b9SJerome Glisse return; 524771fe6b9SJerome Glisse 5259ae47867SAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 526dafc3bd5SChristian Koenig hdmi_detected = 1; 527dafc3bd5SChristian Koenig 528771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 529771fe6b9SJerome Glisse 530771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 531771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 532771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 533771fe6b9SJerome Glisse break; 534771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 535771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 536771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 537771fe6b9SJerome Glisse break; 538771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 539771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 540771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 541771fe6b9SJerome Glisse else 542771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 543771fe6b9SJerome Glisse break; 544771fe6b9SJerome Glisse } 545771fe6b9SJerome Glisse 546a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 547a084e6eeSAlex Deucher return; 548771fe6b9SJerome Glisse 549771fe6b9SJerome Glisse switch (frev) { 550771fe6b9SJerome Glisse case 1: 551771fe6b9SJerome Glisse case 2: 552771fe6b9SJerome Glisse switch (crev) { 553771fe6b9SJerome Glisse case 1: 554771fe6b9SJerome Glisse args.v1.ucMisc = 0; 555771fe6b9SJerome Glisse args.v1.ucAction = action; 556dafc3bd5SChristian Koenig if (hdmi_detected) 557771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 558771fe6b9SJerome Glisse args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 559771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 560edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) 561771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 562edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) 563771fe6b9SJerome Glisse args.v1.ucMisc |= (1 << 1); 564771fe6b9SJerome Glisse } else { 565771fe6b9SJerome Glisse if (dig_connector->linkb) 566771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 567771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 568771fe6b9SJerome Glisse args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 569771fe6b9SJerome Glisse /*if (pScrn->rgbBits == 8) */ 570771fe6b9SJerome Glisse args.v1.ucMisc |= (1 << 1); 571771fe6b9SJerome Glisse } 572771fe6b9SJerome Glisse break; 573771fe6b9SJerome Glisse case 2: 574771fe6b9SJerome Glisse case 3: 575771fe6b9SJerome Glisse args.v2.ucMisc = 0; 576771fe6b9SJerome Glisse args.v2.ucAction = action; 577771fe6b9SJerome Glisse if (crev == 3) { 578771fe6b9SJerome Glisse if (dig->coherent_mode) 579771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 580771fe6b9SJerome Glisse } 581dafc3bd5SChristian Koenig if (hdmi_detected) 582771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 583771fe6b9SJerome Glisse args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 584771fe6b9SJerome Glisse args.v2.ucTruncate = 0; 585771fe6b9SJerome Glisse args.v2.ucSpatial = 0; 586771fe6b9SJerome Glisse args.v2.ucTemporal = 0; 587771fe6b9SJerome Glisse args.v2.ucFRC = 0; 588771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 589edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) 590771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 591edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) { 592771fe6b9SJerome Glisse args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 593edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) 594771fe6b9SJerome Glisse args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 595771fe6b9SJerome Glisse } 596edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) { 597771fe6b9SJerome Glisse args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 598edc664e3SAlex Deucher if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) 599771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 600edc664e3SAlex Deucher if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) 601771fe6b9SJerome Glisse args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 602771fe6b9SJerome Glisse } 603771fe6b9SJerome Glisse } else { 604771fe6b9SJerome Glisse if (dig_connector->linkb) 605771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 606771fe6b9SJerome Glisse if (radeon_encoder->pixel_clock > 165000) 607771fe6b9SJerome Glisse args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 608771fe6b9SJerome Glisse } 609771fe6b9SJerome Glisse break; 610771fe6b9SJerome Glisse default: 611771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 612771fe6b9SJerome Glisse break; 613771fe6b9SJerome Glisse } 614771fe6b9SJerome Glisse break; 615771fe6b9SJerome Glisse default: 616771fe6b9SJerome Glisse DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 617771fe6b9SJerome Glisse break; 618771fe6b9SJerome Glisse } 619771fe6b9SJerome Glisse 620771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 621771fe6b9SJerome Glisse } 622771fe6b9SJerome Glisse 623771fe6b9SJerome Glisse int 624771fe6b9SJerome Glisse atombios_get_encoder_mode(struct drm_encoder *encoder) 625771fe6b9SJerome Glisse { 626771fe6b9SJerome Glisse struct drm_connector *connector; 627771fe6b9SJerome Glisse struct radeon_connector *radeon_connector; 6289ae47867SAlex Deucher struct radeon_connector_atom_dig *dig_connector; 629771fe6b9SJerome Glisse 630771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 631771fe6b9SJerome Glisse if (!connector) 632771fe6b9SJerome Glisse return 0; 633771fe6b9SJerome Glisse 634771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 635771fe6b9SJerome Glisse 636771fe6b9SJerome Glisse switch (connector->connector_type) { 637771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVII: 638705af9c7SAlex Deucher case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ 6390294cf4fSAlex Deucher if (drm_detect_hdmi_monitor(radeon_connector->edid)) 640771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 641771fe6b9SJerome Glisse else if (radeon_connector->use_digital) 642771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 643771fe6b9SJerome Glisse else 644771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 645771fe6b9SJerome Glisse break; 646771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DVID: 647771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_HDMIA: 648771fe6b9SJerome Glisse default: 6490294cf4fSAlex Deucher if (drm_detect_hdmi_monitor(radeon_connector->edid)) 650771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 651771fe6b9SJerome Glisse else 652771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 653771fe6b9SJerome Glisse break; 654771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_LVDS: 655771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_LVDS; 656771fe6b9SJerome Glisse break; 657771fe6b9SJerome Glisse case DRM_MODE_CONNECTOR_DisplayPort: 658196c58d2SAlex Deucher case DRM_MODE_CONNECTOR_eDP: 6599ae47867SAlex Deucher dig_connector = radeon_connector->con_priv; 6609ae47867SAlex Deucher if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 6619ae47867SAlex Deucher (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) 662771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DP; 663f92a8b67SAlex Deucher else if (drm_detect_hdmi_monitor(radeon_connector->edid)) 664771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_HDMI; 665771fe6b9SJerome Glisse else 666771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_DVI; 667771fe6b9SJerome Glisse break; 668a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_DVIA: 669a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_VGA: 670771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_CRT; 671771fe6b9SJerome Glisse break; 672a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_Composite: 673a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_SVIDEO: 674a5899fccSAlex Deucher case DRM_MODE_CONNECTOR_9PinDIN: 675771fe6b9SJerome Glisse /* fix me */ 676771fe6b9SJerome Glisse return ATOM_ENCODER_MODE_TV; 677771fe6b9SJerome Glisse /*return ATOM_ENCODER_MODE_CV;*/ 678771fe6b9SJerome Glisse break; 679771fe6b9SJerome Glisse } 680771fe6b9SJerome Glisse } 681771fe6b9SJerome Glisse 6821a66c95aSAlex Deucher /* 6831a66c95aSAlex Deucher * DIG Encoder/Transmitter Setup 6841a66c95aSAlex Deucher * 6851a66c95aSAlex Deucher * DCE 3.0/3.1 6861a66c95aSAlex Deucher * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. 6871a66c95aSAlex Deucher * Supports up to 3 digital outputs 6881a66c95aSAlex Deucher * - 2 DIG encoder blocks. 6891a66c95aSAlex Deucher * DIG1 can drive UNIPHY link A or link B 6901a66c95aSAlex Deucher * DIG2 can drive UNIPHY link B or LVTMA 6911a66c95aSAlex Deucher * 6921a66c95aSAlex Deucher * DCE 3.2 6931a66c95aSAlex Deucher * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). 6941a66c95aSAlex Deucher * Supports up to 5 digital outputs 6951a66c95aSAlex Deucher * - 2 DIG encoder blocks. 6961a66c95aSAlex Deucher * DIG1/2 can drive UNIPHY0/1/2 link A or link B 6971a66c95aSAlex Deucher * 698bcc1c2a1SAlex Deucher * DCE 4.0 699bcc1c2a1SAlex Deucher * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B). 700bcc1c2a1SAlex Deucher * Supports up to 6 digital outputs 701bcc1c2a1SAlex Deucher * - 6 DIG encoder blocks. 702bcc1c2a1SAlex Deucher * - DIG to PHY mapping is hardcoded 703bcc1c2a1SAlex Deucher * DIG1 drives UNIPHY0 link A, A+B 704bcc1c2a1SAlex Deucher * DIG2 drives UNIPHY0 link B 705bcc1c2a1SAlex Deucher * DIG3 drives UNIPHY1 link A, A+B 706bcc1c2a1SAlex Deucher * DIG4 drives UNIPHY1 link B 707bcc1c2a1SAlex Deucher * DIG5 drives UNIPHY2 link A, A+B 708bcc1c2a1SAlex Deucher * DIG6 drives UNIPHY2 link B 709bcc1c2a1SAlex Deucher * 7101a66c95aSAlex Deucher * Routing 7111a66c95aSAlex Deucher * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) 7121a66c95aSAlex Deucher * Examples: 7131a66c95aSAlex Deucher * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI 7141a66c95aSAlex Deucher * crtc1 -> dig1 -> UNIPHY0 link B -> DP 7151a66c95aSAlex Deucher * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS 7161a66c95aSAlex Deucher * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI 7171a66c95aSAlex Deucher */ 718bcc1c2a1SAlex Deucher 719bcc1c2a1SAlex Deucher union dig_encoder_control { 720bcc1c2a1SAlex Deucher DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 721bcc1c2a1SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 722bcc1c2a1SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 723bcc1c2a1SAlex Deucher }; 724bcc1c2a1SAlex Deucher 725bcc1c2a1SAlex Deucher void 726771fe6b9SJerome Glisse atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) 727771fe6b9SJerome Glisse { 728771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 729771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 730771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 7319ae47867SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 7329ae47867SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 7339ae47867SAlex Deucher radeon_get_atom_connector_priv_from_encoder(encoder); 734bcc1c2a1SAlex Deucher union dig_encoder_control args; 735d9c9fe36SAlex Deucher int index = 0; 736771fe6b9SJerome Glisse uint8_t frev, crev; 737771fe6b9SJerome Glisse 7389ae47867SAlex Deucher if (!dig || !dig_connector) 739771fe6b9SJerome Glisse return; 740771fe6b9SJerome Glisse 741771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 742771fe6b9SJerome Glisse 743bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) 744bcc1c2a1SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 745bcc1c2a1SAlex Deucher else { 746f28cf339SDave Airlie if (dig->dig_encoder) 747771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 748771fe6b9SJerome Glisse else 749771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 750bcc1c2a1SAlex Deucher } 751771fe6b9SJerome Glisse 752a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 753a084e6eeSAlex Deucher return; 754771fe6b9SJerome Glisse 755bcc1c2a1SAlex Deucher args.v1.ucAction = action; 756bcc1c2a1SAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 757bcc1c2a1SAlex Deucher args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); 758771fe6b9SJerome Glisse 759bcc1c2a1SAlex Deucher if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) { 760bcc1c2a1SAlex Deucher if (dig_connector->dp_clock == 270000) 761bcc1c2a1SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 762bcc1c2a1SAlex Deucher args.v1.ucLaneNum = dig_connector->dp_lane_count; 763bcc1c2a1SAlex Deucher } else if (radeon_encoder->pixel_clock > 165000) 764bcc1c2a1SAlex Deucher args.v1.ucLaneNum = 8; 765bcc1c2a1SAlex Deucher else 766bcc1c2a1SAlex Deucher args.v1.ucLaneNum = 4; 767bcc1c2a1SAlex Deucher 768bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 769bcc1c2a1SAlex Deucher args.v3.acConfig.ucDigSel = dig->dig_encoder; 770bcc1c2a1SAlex Deucher args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; 771771fe6b9SJerome Glisse } else { 772771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 773771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 774bcc1c2a1SAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 775771fe6b9SJerome Glisse break; 776bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 777771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 778bcc1c2a1SAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 779bcc1c2a1SAlex Deucher break; 780bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 781bcc1c2a1SAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 782771fe6b9SJerome Glisse break; 783771fe6b9SJerome Glisse } 784771fe6b9SJerome Glisse if (dig_connector->linkb) 785bcc1c2a1SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 786771fe6b9SJerome Glisse else 787bcc1c2a1SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 788bcc1c2a1SAlex Deucher } 789771fe6b9SJerome Glisse 790771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 791771fe6b9SJerome Glisse 792771fe6b9SJerome Glisse } 793771fe6b9SJerome Glisse 794771fe6b9SJerome Glisse union dig_transmitter_control { 795771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 796771fe6b9SJerome Glisse DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 797bcc1c2a1SAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 798771fe6b9SJerome Glisse }; 799771fe6b9SJerome Glisse 8005801ead6SAlex Deucher void 8011a66c95aSAlex Deucher atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) 802771fe6b9SJerome Glisse { 803771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 804771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 805771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 8069ae47867SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 8079ae47867SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 8089ae47867SAlex Deucher radeon_get_atom_connector_priv_from_encoder(encoder); 8099ae47867SAlex Deucher struct drm_connector *connector; 8109ae47867SAlex Deucher struct radeon_connector *radeon_connector; 811771fe6b9SJerome Glisse union dig_transmitter_control args; 812d9c9fe36SAlex Deucher int index = 0; 813771fe6b9SJerome Glisse uint8_t frev, crev; 814f92a8b67SAlex Deucher bool is_dp = false; 815bcc1c2a1SAlex Deucher int pll_id = 0; 816771fe6b9SJerome Glisse 8179ae47867SAlex Deucher if (!dig || !dig_connector) 8189ae47867SAlex Deucher return; 8199ae47867SAlex Deucher 820771fe6b9SJerome Glisse connector = radeon_get_connector_for_encoder(encoder); 821771fe6b9SJerome Glisse radeon_connector = to_radeon_connector(connector); 822771fe6b9SJerome Glisse 823f92a8b67SAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) 824f92a8b67SAlex Deucher is_dp = true; 825f92a8b67SAlex Deucher 826771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 827771fe6b9SJerome Glisse 828bcc1c2a1SAlex Deucher if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev)) 829771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 830771fe6b9SJerome Glisse else { 831771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 832771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 833771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); 834771fe6b9SJerome Glisse break; 835771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 836771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); 837771fe6b9SJerome Glisse break; 838771fe6b9SJerome Glisse } 839771fe6b9SJerome Glisse } 840771fe6b9SJerome Glisse 841a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 842a084e6eeSAlex Deucher return; 843771fe6b9SJerome Glisse 844771fe6b9SJerome Glisse args.v1.ucAction = action; 845f95a9f0bSAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 846f95a9f0bSAlex Deucher args.v1.usInitInfo = radeon_connector->connector_object_id; 8471a66c95aSAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 8481a66c95aSAlex Deucher args.v1.asMode.ucLaneSel = lane_num; 8491a66c95aSAlex Deucher args.v1.asMode.ucLaneSet = lane_set; 850771fe6b9SJerome Glisse } else { 851f92a8b67SAlex Deucher if (is_dp) 852f92a8b67SAlex Deucher args.v1.usPixelClock = 8535801ead6SAlex Deucher cpu_to_le16(dig_connector->dp_clock / 10); 854f92a8b67SAlex Deucher else if (radeon_encoder->pixel_clock > 165000) 855f95a9f0bSAlex Deucher args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 856f95a9f0bSAlex Deucher else 857f95a9f0bSAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 858771fe6b9SJerome Glisse } 859bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 860bcc1c2a1SAlex Deucher if (is_dp) 861bcc1c2a1SAlex Deucher args.v3.ucLaneNum = dig_connector->dp_lane_count; 862bcc1c2a1SAlex Deucher else if (radeon_encoder->pixel_clock > 165000) 863bcc1c2a1SAlex Deucher args.v3.ucLaneNum = 8; 864bcc1c2a1SAlex Deucher else 865bcc1c2a1SAlex Deucher args.v3.ucLaneNum = 4; 866bcc1c2a1SAlex Deucher 867bcc1c2a1SAlex Deucher if (dig_connector->linkb) { 868bcc1c2a1SAlex Deucher args.v3.acConfig.ucLinkSel = 1; 869bcc1c2a1SAlex Deucher args.v3.acConfig.ucEncoderSel = 1; 870bcc1c2a1SAlex Deucher } 871bcc1c2a1SAlex Deucher 872bcc1c2a1SAlex Deucher /* Select the PLL for the PHY 873bcc1c2a1SAlex Deucher * DP PHY should be clocked from external src if there is 874bcc1c2a1SAlex Deucher * one. 875bcc1c2a1SAlex Deucher */ 876bcc1c2a1SAlex Deucher if (encoder->crtc) { 877bcc1c2a1SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 878bcc1c2a1SAlex Deucher pll_id = radeon_crtc->pll_id; 879bcc1c2a1SAlex Deucher } 880bcc1c2a1SAlex Deucher if (is_dp && rdev->clock.dp_extclk) 881bcc1c2a1SAlex Deucher args.v3.acConfig.ucRefClkSource = 2; /* external src */ 882bcc1c2a1SAlex Deucher else 883bcc1c2a1SAlex Deucher args.v3.acConfig.ucRefClkSource = pll_id; 884bcc1c2a1SAlex Deucher 885bcc1c2a1SAlex Deucher switch (radeon_encoder->encoder_id) { 886bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 887bcc1c2a1SAlex Deucher args.v3.acConfig.ucTransmitterSel = 0; 888bcc1c2a1SAlex Deucher break; 889bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 890bcc1c2a1SAlex Deucher args.v3.acConfig.ucTransmitterSel = 1; 891bcc1c2a1SAlex Deucher break; 892bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 893bcc1c2a1SAlex Deucher args.v3.acConfig.ucTransmitterSel = 2; 894bcc1c2a1SAlex Deucher break; 895bcc1c2a1SAlex Deucher } 896bcc1c2a1SAlex Deucher 897bcc1c2a1SAlex Deucher if (is_dp) 898bcc1c2a1SAlex Deucher args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ 899bcc1c2a1SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 900bcc1c2a1SAlex Deucher if (dig->coherent_mode) 901bcc1c2a1SAlex Deucher args.v3.acConfig.fCoherentMode = 1; 902b317a9ceSAlex Deucher if (radeon_encoder->pixel_clock > 165000) 903b317a9ceSAlex Deucher args.v3.acConfig.fDualLinkConnector = 1; 904bcc1c2a1SAlex Deucher } 905bcc1c2a1SAlex Deucher } else if (ASIC_IS_DCE32(rdev)) { 906d9c9fe36SAlex Deucher args.v2.acConfig.ucEncoderSel = dig->dig_encoder; 9071a66c95aSAlex Deucher if (dig_connector->linkb) 9081a66c95aSAlex Deucher args.v2.acConfig.ucLinkSel = 1; 909771fe6b9SJerome Glisse 910771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 911771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 912771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 0; 913771fe6b9SJerome Glisse break; 914771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 915771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 1; 916771fe6b9SJerome Glisse break; 917771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 918771fe6b9SJerome Glisse args.v2.acConfig.ucTransmitterSel = 2; 919771fe6b9SJerome Glisse break; 920771fe6b9SJerome Glisse } 921771fe6b9SJerome Glisse 922f92a8b67SAlex Deucher if (is_dp) 923f92a8b67SAlex Deucher args.v2.acConfig.fCoherentMode = 1; 924f92a8b67SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 925771fe6b9SJerome Glisse if (dig->coherent_mode) 926771fe6b9SJerome Glisse args.v2.acConfig.fCoherentMode = 1; 927b317a9ceSAlex Deucher if (radeon_encoder->pixel_clock > 165000) 928b317a9ceSAlex Deucher args.v2.acConfig.fDualLinkConnector = 1; 929771fe6b9SJerome Glisse } 930771fe6b9SJerome Glisse } else { 931771fe6b9SJerome Glisse args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 932771fe6b9SJerome Glisse 933f28cf339SDave Airlie if (dig->dig_encoder) 9341a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 9351a66c95aSAlex Deucher else 936771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 937f28cf339SDave Airlie 938d9c9fe36SAlex Deucher if ((rdev->flags & RADEON_IS_IGP) && 939d9c9fe36SAlex Deucher (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 940d9c9fe36SAlex Deucher if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { 941771fe6b9SJerome Glisse if (dig_connector->igp_lane_info & 0x1) 942771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 943771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x2) 944771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 945771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x4) 946771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 947771fe6b9SJerome Glisse else if (dig_connector->igp_lane_info & 0x8) 948771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 949d9c9fe36SAlex Deucher } else { 950d9c9fe36SAlex Deucher if (dig_connector->igp_lane_info & 0x3) 951d9c9fe36SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 952d9c9fe36SAlex Deucher else if (dig_connector->igp_lane_info & 0xc) 953d9c9fe36SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 954771fe6b9SJerome Glisse } 955771fe6b9SJerome Glisse } 9561a66c95aSAlex Deucher 9571a66c95aSAlex Deucher if (dig_connector->linkb) 9581a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 9591a66c95aSAlex Deucher else 9601a66c95aSAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 9611a66c95aSAlex Deucher 962f92a8b67SAlex Deucher if (is_dp) 963f92a8b67SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 964f92a8b67SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 965771fe6b9SJerome Glisse if (dig->coherent_mode) 966771fe6b9SJerome Glisse args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 967d9c9fe36SAlex Deucher if (radeon_encoder->pixel_clock > 165000) 968d9c9fe36SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 969771fe6b9SJerome Glisse } 970771fe6b9SJerome Glisse } 971771fe6b9SJerome Glisse 972771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 973771fe6b9SJerome Glisse } 974771fe6b9SJerome Glisse 975771fe6b9SJerome Glisse static void 976771fe6b9SJerome Glisse atombios_yuv_setup(struct drm_encoder *encoder, bool enable) 977771fe6b9SJerome Glisse { 978771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 979771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 980771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 981771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 982771fe6b9SJerome Glisse ENABLE_YUV_PS_ALLOCATION args; 983771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 984771fe6b9SJerome Glisse uint32_t temp, reg; 985771fe6b9SJerome Glisse 986771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 987771fe6b9SJerome Glisse 988771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 989771fe6b9SJerome Glisse reg = R600_BIOS_3_SCRATCH; 990771fe6b9SJerome Glisse else 991771fe6b9SJerome Glisse reg = RADEON_BIOS_3_SCRATCH; 992771fe6b9SJerome Glisse 993771fe6b9SJerome Glisse /* XXX: fix up scratch reg handling */ 994771fe6b9SJerome Glisse temp = RREG32(reg); 9954ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 996771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_TV1_ACTIVE | 997771fe6b9SJerome Glisse (radeon_crtc->crtc_id << 18))); 9984ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 999771fe6b9SJerome Glisse WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); 1000771fe6b9SJerome Glisse else 1001771fe6b9SJerome Glisse WREG32(reg, 0); 1002771fe6b9SJerome Glisse 1003771fe6b9SJerome Glisse if (enable) 1004771fe6b9SJerome Glisse args.ucEnable = ATOM_ENABLE; 1005771fe6b9SJerome Glisse args.ucCRTC = radeon_crtc->crtc_id; 1006771fe6b9SJerome Glisse 1007771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1008771fe6b9SJerome Glisse 1009771fe6b9SJerome Glisse WREG32(reg, temp); 1010771fe6b9SJerome Glisse } 1011771fe6b9SJerome Glisse 1012771fe6b9SJerome Glisse static void 1013771fe6b9SJerome Glisse radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) 1014771fe6b9SJerome Glisse { 1015771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1016771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1017771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1018771fe6b9SJerome Glisse DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1019771fe6b9SJerome Glisse int index = 0; 1020771fe6b9SJerome Glisse bool is_dig = false; 1021771fe6b9SJerome Glisse 1022771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1023771fe6b9SJerome Glisse 1024*d9fdaafbSDave Airlie DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 10254ce001abSDave Airlie radeon_encoder->encoder_id, mode, radeon_encoder->devices, 10264ce001abSDave Airlie radeon_encoder->active_device); 1027771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1028771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1029771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1030771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1031771fe6b9SJerome Glisse break; 1032771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1033771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1034771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1035771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1036771fe6b9SJerome Glisse is_dig = true; 1037771fe6b9SJerome Glisse break; 1038771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1039771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1040771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1041771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1042771fe6b9SJerome Glisse break; 1043771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1044771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1045771fe6b9SJerome Glisse break; 1046771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1047771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 1048771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1049771fe6b9SJerome Glisse else 1050771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1051771fe6b9SJerome Glisse break; 1052771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1053771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 10548c2a6d73SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1055771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 10568c2a6d73SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1057771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1058771fe6b9SJerome Glisse else 1059771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1060771fe6b9SJerome Glisse break; 1061771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1062771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 10638c2a6d73SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1064771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 10658c2a6d73SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1066771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1067771fe6b9SJerome Glisse else 1068771fe6b9SJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1069771fe6b9SJerome Glisse break; 1070771fe6b9SJerome Glisse } 1071771fe6b9SJerome Glisse 1072771fe6b9SJerome Glisse if (is_dig) { 1073771fe6b9SJerome Glisse switch (mode) { 1074771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 1075a5f798ceSAlex Deucher if (!ASIC_IS_DCE4(rdev)) 1076a5f798ceSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); 1077fb668c2fSAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { 107858682f10SDave Airlie struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 1079fb668c2fSAlex Deucher 108058682f10SDave Airlie dp_link_train(encoder, connector); 1081fb668c2fSAlex Deucher if (ASIC_IS_DCE4(rdev)) 1082fb668c2fSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); 108358682f10SDave Airlie } 1084771fe6b9SJerome Glisse break; 1085771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 1086771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 1087771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 1088fb668c2fSAlex Deucher if (!ASIC_IS_DCE4(rdev)) 108958682f10SDave Airlie atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); 1090fb668c2fSAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { 1091fb668c2fSAlex Deucher if (ASIC_IS_DCE4(rdev)) 1092fb668c2fSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1093fb668c2fSAlex Deucher } 1094771fe6b9SJerome Glisse break; 1095771fe6b9SJerome Glisse } 1096771fe6b9SJerome Glisse } else { 1097771fe6b9SJerome Glisse switch (mode) { 1098771fe6b9SJerome Glisse case DRM_MODE_DPMS_ON: 1099771fe6b9SJerome Glisse args.ucAction = ATOM_ENABLE; 1100771fe6b9SJerome Glisse break; 1101771fe6b9SJerome Glisse case DRM_MODE_DPMS_STANDBY: 1102771fe6b9SJerome Glisse case DRM_MODE_DPMS_SUSPEND: 1103771fe6b9SJerome Glisse case DRM_MODE_DPMS_OFF: 1104771fe6b9SJerome Glisse args.ucAction = ATOM_DISABLE; 1105771fe6b9SJerome Glisse break; 1106771fe6b9SJerome Glisse } 1107771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1108771fe6b9SJerome Glisse } 1109771fe6b9SJerome Glisse radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1110c913e23aSRafał Miłecki 1111771fe6b9SJerome Glisse } 1112771fe6b9SJerome Glisse 11139ae47867SAlex Deucher union crtc_source_param { 1114771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 1115771fe6b9SJerome Glisse SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 1116771fe6b9SJerome Glisse }; 1117771fe6b9SJerome Glisse 1118771fe6b9SJerome Glisse static void 1119771fe6b9SJerome Glisse atombios_set_encoder_crtc_source(struct drm_encoder *encoder) 1120771fe6b9SJerome Glisse { 1121771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1122771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1123771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1124771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 11259ae47867SAlex Deucher union crtc_source_param args; 1126771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 1127771fe6b9SJerome Glisse uint8_t frev, crev; 1128f28cf339SDave Airlie struct radeon_encoder_atom_dig *dig; 1129771fe6b9SJerome Glisse 1130771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1131771fe6b9SJerome Glisse 1132a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1133a084e6eeSAlex Deucher return; 1134771fe6b9SJerome Glisse 1135771fe6b9SJerome Glisse switch (frev) { 1136771fe6b9SJerome Glisse case 1: 1137771fe6b9SJerome Glisse switch (crev) { 1138771fe6b9SJerome Glisse case 1: 1139771fe6b9SJerome Glisse default: 1140771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev)) 1141771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 1142771fe6b9SJerome Glisse else { 1143771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { 1144771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id; 1145771fe6b9SJerome Glisse } else { 1146771fe6b9SJerome Glisse args.v1.ucCRTC = radeon_crtc->crtc_id << 2; 1147771fe6b9SJerome Glisse } 1148771fe6b9SJerome Glisse } 1149771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1150771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1151771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1152771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 1153771fe6b9SJerome Glisse break; 1154771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1155771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1156771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) 1157771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 1158771fe6b9SJerome Glisse else 1159771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 1160771fe6b9SJerome Glisse break; 1161771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1162771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1163771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1164771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 1165771fe6b9SJerome Glisse break; 1166771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1167771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 11684ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1169771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 11704ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1171771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1172771fe6b9SJerome Glisse else 1173771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 1174771fe6b9SJerome Glisse break; 1175771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1176771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 11774ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1178771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 11794ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1180771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 1181771fe6b9SJerome Glisse else 1182771fe6b9SJerome Glisse args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 1183771fe6b9SJerome Glisse break; 1184771fe6b9SJerome Glisse } 1185771fe6b9SJerome Glisse break; 1186771fe6b9SJerome Glisse case 2: 1187771fe6b9SJerome Glisse args.v2.ucCRTC = radeon_crtc->crtc_id; 1188771fe6b9SJerome Glisse args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 1189771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1190771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1191771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1192771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1193f28cf339SDave Airlie case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1194f28cf339SDave Airlie dig = radeon_encoder->enc_priv; 1195bcc1c2a1SAlex Deucher switch (dig->dig_encoder) { 1196bcc1c2a1SAlex Deucher case 0: 1197771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 1198771fe6b9SJerome Glisse break; 1199bcc1c2a1SAlex Deucher case 1: 1200bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 1201bcc1c2a1SAlex Deucher break; 1202bcc1c2a1SAlex Deucher case 2: 1203bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 1204bcc1c2a1SAlex Deucher break; 1205bcc1c2a1SAlex Deucher case 3: 1206bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 1207bcc1c2a1SAlex Deucher break; 1208bcc1c2a1SAlex Deucher case 4: 1209bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 1210bcc1c2a1SAlex Deucher break; 1211bcc1c2a1SAlex Deucher case 5: 1212bcc1c2a1SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 1213bcc1c2a1SAlex Deucher break; 1214bcc1c2a1SAlex Deucher } 1215bcc1c2a1SAlex Deucher break; 1216771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1217771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 1218771fe6b9SJerome Glisse break; 1219771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 12204ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1221771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 12224ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1223771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1224771fe6b9SJerome Glisse else 1225771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 1226771fe6b9SJerome Glisse break; 1227771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 12284ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1229771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 12304ce001abSDave Airlie else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1231771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 1232771fe6b9SJerome Glisse else 1233771fe6b9SJerome Glisse args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 1234771fe6b9SJerome Glisse break; 1235771fe6b9SJerome Glisse } 1236771fe6b9SJerome Glisse break; 1237771fe6b9SJerome Glisse } 1238771fe6b9SJerome Glisse break; 1239771fe6b9SJerome Glisse default: 1240771fe6b9SJerome Glisse DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 1241771fe6b9SJerome Glisse break; 1242771fe6b9SJerome Glisse } 1243771fe6b9SJerome Glisse 1244771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1245267364acSAlex Deucher 1246267364acSAlex Deucher /* update scratch regs with new routing */ 1247267364acSAlex Deucher radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1248771fe6b9SJerome Glisse } 1249771fe6b9SJerome Glisse 1250771fe6b9SJerome Glisse static void 1251771fe6b9SJerome Glisse atombios_apply_encoder_quirks(struct drm_encoder *encoder, 1252771fe6b9SJerome Glisse struct drm_display_mode *mode) 1253771fe6b9SJerome Glisse { 1254771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1255771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1256771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1257771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1258771fe6b9SJerome Glisse 1259771fe6b9SJerome Glisse /* Funky macbooks */ 1260771fe6b9SJerome Glisse if ((dev->pdev->device == 0x71C5) && 1261771fe6b9SJerome Glisse (dev->pdev->subsystem_vendor == 0x106b) && 1262771fe6b9SJerome Glisse (dev->pdev->subsystem_device == 0x0080)) { 1263771fe6b9SJerome Glisse if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 1264771fe6b9SJerome Glisse uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 1265771fe6b9SJerome Glisse 1266771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 1267771fe6b9SJerome Glisse lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 1268771fe6b9SJerome Glisse 1269771fe6b9SJerome Glisse WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 1270771fe6b9SJerome Glisse } 1271771fe6b9SJerome Glisse } 1272771fe6b9SJerome Glisse 1273771fe6b9SJerome Glisse /* set scaler clears this on some chips */ 1274bcc1c2a1SAlex Deucher /* XXX check DCE4 */ 1275ceefedd8SAlex Deucher if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) { 1276771fe6b9SJerome Glisse if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE)) 1277ceefedd8SAlex Deucher WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 1278ceefedd8SAlex Deucher AVIVO_D1MODE_INTERLEAVE_EN); 1279ceefedd8SAlex Deucher } 1280771fe6b9SJerome Glisse } 1281771fe6b9SJerome Glisse 1282f28cf339SDave Airlie static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) 1283f28cf339SDave Airlie { 1284f28cf339SDave Airlie struct drm_device *dev = encoder->dev; 1285f28cf339SDave Airlie struct radeon_device *rdev = dev->dev_private; 1286f28cf339SDave Airlie struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1287f28cf339SDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1288f28cf339SDave Airlie struct drm_encoder *test_encoder; 1289f28cf339SDave Airlie struct radeon_encoder_atom_dig *dig; 1290f28cf339SDave Airlie uint32_t dig_enc_in_use = 0; 1291bcc1c2a1SAlex Deucher 1292bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 1293bcc1c2a1SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 1294bcc1c2a1SAlex Deucher radeon_get_atom_connector_priv_from_encoder(encoder); 1295bcc1c2a1SAlex Deucher 1296bcc1c2a1SAlex Deucher switch (radeon_encoder->encoder_id) { 1297bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1298bcc1c2a1SAlex Deucher if (dig_connector->linkb) 1299bcc1c2a1SAlex Deucher return 1; 1300bcc1c2a1SAlex Deucher else 1301bcc1c2a1SAlex Deucher return 0; 1302bcc1c2a1SAlex Deucher break; 1303bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1304bcc1c2a1SAlex Deucher if (dig_connector->linkb) 1305bcc1c2a1SAlex Deucher return 3; 1306bcc1c2a1SAlex Deucher else 1307bcc1c2a1SAlex Deucher return 2; 1308bcc1c2a1SAlex Deucher break; 1309bcc1c2a1SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1310bcc1c2a1SAlex Deucher if (dig_connector->linkb) 1311bcc1c2a1SAlex Deucher return 5; 1312bcc1c2a1SAlex Deucher else 1313bcc1c2a1SAlex Deucher return 4; 1314bcc1c2a1SAlex Deucher break; 1315bcc1c2a1SAlex Deucher } 1316bcc1c2a1SAlex Deucher } 1317bcc1c2a1SAlex Deucher 1318f28cf339SDave Airlie /* on DCE32 and encoder can driver any block so just crtc id */ 1319f28cf339SDave Airlie if (ASIC_IS_DCE32(rdev)) { 1320f28cf339SDave Airlie return radeon_crtc->crtc_id; 1321f28cf339SDave Airlie } 1322f28cf339SDave Airlie 1323f28cf339SDave Airlie /* on DCE3 - LVTMA can only be driven by DIGB */ 1324f28cf339SDave Airlie list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 1325f28cf339SDave Airlie struct radeon_encoder *radeon_test_encoder; 1326f28cf339SDave Airlie 1327f28cf339SDave Airlie if (encoder == test_encoder) 1328f28cf339SDave Airlie continue; 1329f28cf339SDave Airlie 1330f28cf339SDave Airlie if (!radeon_encoder_is_digital(test_encoder)) 1331f28cf339SDave Airlie continue; 1332f28cf339SDave Airlie 1333f28cf339SDave Airlie radeon_test_encoder = to_radeon_encoder(test_encoder); 1334f28cf339SDave Airlie dig = radeon_test_encoder->enc_priv; 1335f28cf339SDave Airlie 1336f28cf339SDave Airlie if (dig->dig_encoder >= 0) 1337f28cf339SDave Airlie dig_enc_in_use |= (1 << dig->dig_encoder); 1338f28cf339SDave Airlie } 1339f28cf339SDave Airlie 1340f28cf339SDave Airlie if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { 1341f28cf339SDave Airlie if (dig_enc_in_use & 0x2) 1342f28cf339SDave Airlie DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n"); 1343f28cf339SDave Airlie return 1; 1344f28cf339SDave Airlie } 1345f28cf339SDave Airlie if (!(dig_enc_in_use & 1)) 1346f28cf339SDave Airlie return 0; 1347f28cf339SDave Airlie return 1; 1348f28cf339SDave Airlie } 1349f28cf339SDave Airlie 1350771fe6b9SJerome Glisse static void 1351771fe6b9SJerome Glisse radeon_atom_encoder_mode_set(struct drm_encoder *encoder, 1352771fe6b9SJerome Glisse struct drm_display_mode *mode, 1353771fe6b9SJerome Glisse struct drm_display_mode *adjusted_mode) 1354771fe6b9SJerome Glisse { 1355771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1356771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1357771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1358771fe6b9SJerome Glisse 1359771fe6b9SJerome Glisse radeon_encoder->pixel_clock = adjusted_mode->clock; 1360771fe6b9SJerome Glisse 1361c6f8505eSAlex Deucher if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { 13624ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 1363771fe6b9SJerome Glisse atombios_yuv_setup(encoder, true); 1364771fe6b9SJerome Glisse else 1365771fe6b9SJerome Glisse atombios_yuv_setup(encoder, false); 1366771fe6b9SJerome Glisse } 1367771fe6b9SJerome Glisse 1368771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1369771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1370771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1371771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1372771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1373771fe6b9SJerome Glisse atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 1374771fe6b9SJerome Glisse break; 1375771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1376771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1377771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1378771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1379bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 1380bcc1c2a1SAlex Deucher /* disable the transmitter */ 1381bcc1c2a1SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1382bcc1c2a1SAlex Deucher /* setup and enable the encoder */ 1383bcc1c2a1SAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP); 1384bcc1c2a1SAlex Deucher 1385bcc1c2a1SAlex Deucher /* init and enable the transmitter */ 1386bcc1c2a1SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 1387bcc1c2a1SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1388bcc1c2a1SAlex Deucher } else { 1389771fe6b9SJerome Glisse /* disable the encoder and transmitter */ 13901a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1391771fe6b9SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_DISABLE); 1392771fe6b9SJerome Glisse 1393771fe6b9SJerome Glisse /* setup and enable the encoder and transmitter */ 1394771fe6b9SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_ENABLE); 13951a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 13961a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 13971a66c95aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 1398bcc1c2a1SAlex Deucher } 1399771fe6b9SJerome Glisse break; 1400771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1401771fe6b9SJerome Glisse atombios_ddia_setup(encoder, ATOM_ENABLE); 1402771fe6b9SJerome Glisse break; 1403771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1404771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1405771fe6b9SJerome Glisse atombios_external_tmds_setup(encoder, ATOM_ENABLE); 1406771fe6b9SJerome Glisse break; 1407771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1408771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1409771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1410771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1411771fe6b9SJerome Glisse atombios_dac_setup(encoder, ATOM_ENABLE); 1412d3a67a43SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { 14134ce001abSDave Airlie if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1414771fe6b9SJerome Glisse atombios_tv_setup(encoder, ATOM_ENABLE); 1415d3a67a43SAlex Deucher else 1416d3a67a43SAlex Deucher atombios_tv_setup(encoder, ATOM_DISABLE); 1417d3a67a43SAlex Deucher } 1418771fe6b9SJerome Glisse break; 1419771fe6b9SJerome Glisse } 1420771fe6b9SJerome Glisse atombios_apply_encoder_quirks(encoder, adjusted_mode); 1421dafc3bd5SChristian Koenig 14222cd6218cSRafał Miłecki if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { 14232cd6218cSRafał Miłecki r600_hdmi_enable(encoder); 1424dafc3bd5SChristian Koenig r600_hdmi_setmode(encoder, adjusted_mode); 1425771fe6b9SJerome Glisse } 14262cd6218cSRafał Miłecki } 1427771fe6b9SJerome Glisse 1428771fe6b9SJerome Glisse static bool 14294ce001abSDave Airlie atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1430771fe6b9SJerome Glisse { 1431771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1432771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1433771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 14344ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1435771fe6b9SJerome Glisse 1436771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | 1437771fe6b9SJerome Glisse ATOM_DEVICE_CV_SUPPORT | 1438771fe6b9SJerome Glisse ATOM_DEVICE_CRT_SUPPORT)) { 1439771fe6b9SJerome Glisse DAC_LOAD_DETECTION_PS_ALLOCATION args; 1440771fe6b9SJerome Glisse int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1441771fe6b9SJerome Glisse uint8_t frev, crev; 1442771fe6b9SJerome Glisse 1443771fe6b9SJerome Glisse memset(&args, 0, sizeof(args)); 1444771fe6b9SJerome Glisse 1445a084e6eeSAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 1446a084e6eeSAlex Deucher return false; 1447771fe6b9SJerome Glisse 1448771fe6b9SJerome Glisse args.sDacload.ucMisc = 0; 1449771fe6b9SJerome Glisse 1450771fe6b9SJerome Glisse if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 1451771fe6b9SJerome Glisse (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) 1452771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_A; 1453771fe6b9SJerome Glisse else 1454771fe6b9SJerome Glisse args.sDacload.ucDacType = ATOM_DAC_B; 1455771fe6b9SJerome Glisse 14564ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) 1457771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 14584ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) 1459771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 14604ce001abSDave Airlie else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1461771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 1462771fe6b9SJerome Glisse if (crev >= 3) 1463771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 14644ce001abSDave Airlie } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1465771fe6b9SJerome Glisse args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 1466771fe6b9SJerome Glisse if (crev >= 3) 1467771fe6b9SJerome Glisse args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1468771fe6b9SJerome Glisse } 1469771fe6b9SJerome Glisse 1470771fe6b9SJerome Glisse atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1471771fe6b9SJerome Glisse 1472771fe6b9SJerome Glisse return true; 1473771fe6b9SJerome Glisse } else 1474771fe6b9SJerome Glisse return false; 1475771fe6b9SJerome Glisse } 1476771fe6b9SJerome Glisse 1477771fe6b9SJerome Glisse static enum drm_connector_status 1478771fe6b9SJerome Glisse radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 1479771fe6b9SJerome Glisse { 1480771fe6b9SJerome Glisse struct drm_device *dev = encoder->dev; 1481771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1482771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 14834ce001abSDave Airlie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 1484771fe6b9SJerome Glisse uint32_t bios_0_scratch; 1485771fe6b9SJerome Glisse 14864ce001abSDave Airlie if (!atombios_dac_load_detect(encoder, connector)) { 1487*d9fdaafbSDave Airlie DRM_DEBUG_KMS("detect returned false \n"); 1488771fe6b9SJerome Glisse return connector_status_unknown; 1489771fe6b9SJerome Glisse } 1490771fe6b9SJerome Glisse 1491771fe6b9SJerome Glisse if (rdev->family >= CHIP_R600) 1492771fe6b9SJerome Glisse bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 1493771fe6b9SJerome Glisse else 1494771fe6b9SJerome Glisse bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 1495771fe6b9SJerome Glisse 1496*d9fdaafbSDave Airlie DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 14974ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 1498771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT1_MASK) 1499771fe6b9SJerome Glisse return connector_status_connected; 15004ce001abSDave Airlie } 15014ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 1502771fe6b9SJerome Glisse if (bios_0_scratch & ATOM_S0_CRT2_MASK) 1503771fe6b9SJerome Glisse return connector_status_connected; 15044ce001abSDave Airlie } 15054ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 1506771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 1507771fe6b9SJerome Glisse return connector_status_connected; 15084ce001abSDave Airlie } 15094ce001abSDave Airlie if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 1510771fe6b9SJerome Glisse if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 1511771fe6b9SJerome Glisse return connector_status_connected; /* CTV */ 1512771fe6b9SJerome Glisse else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 1513771fe6b9SJerome Glisse return connector_status_connected; /* STV */ 1514771fe6b9SJerome Glisse } 1515771fe6b9SJerome Glisse return connector_status_disconnected; 1516771fe6b9SJerome Glisse } 1517771fe6b9SJerome Glisse 1518771fe6b9SJerome Glisse static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) 1519771fe6b9SJerome Glisse { 1520267364acSAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1521267364acSAlex Deucher 1522267364acSAlex Deucher if (radeon_encoder->active_device & 1523267364acSAlex Deucher (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { 1524267364acSAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 1525267364acSAlex Deucher if (dig) 1526267364acSAlex Deucher dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); 1527267364acSAlex Deucher } 1528267364acSAlex Deucher 1529771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, true); 1530771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 1531267364acSAlex Deucher 1532267364acSAlex Deucher /* this is needed for the pll/ss setup to work correctly in some cases */ 1533267364acSAlex Deucher atombios_set_encoder_crtc_source(encoder); 1534771fe6b9SJerome Glisse } 1535771fe6b9SJerome Glisse 1536771fe6b9SJerome Glisse static void radeon_atom_encoder_commit(struct drm_encoder *encoder) 1537771fe6b9SJerome Glisse { 1538771fe6b9SJerome Glisse radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 1539771fe6b9SJerome Glisse radeon_atom_output_lock(encoder, false); 1540771fe6b9SJerome Glisse } 1541771fe6b9SJerome Glisse 15424ce001abSDave Airlie static void radeon_atom_encoder_disable(struct drm_encoder *encoder) 15434ce001abSDave Airlie { 1544aa961391SAlex Deucher struct drm_device *dev = encoder->dev; 1545aa961391SAlex Deucher struct radeon_device *rdev = dev->dev_private; 15464ce001abSDave Airlie struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1547f28cf339SDave Airlie struct radeon_encoder_atom_dig *dig; 15484ce001abSDave Airlie radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 1549f28cf339SDave Airlie 1550aa961391SAlex Deucher switch (radeon_encoder->encoder_id) { 1551aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1552aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1553aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1554aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1555aa961391SAlex Deucher atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE); 1556aa961391SAlex Deucher break; 1557aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1558aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1559aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1560aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1561aa961391SAlex Deucher if (ASIC_IS_DCE4(rdev)) 1562aa961391SAlex Deucher /* disable the transmitter */ 1563aa961391SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1564aa961391SAlex Deucher else { 1565aa961391SAlex Deucher /* disable the encoder and transmitter */ 1566aa961391SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 1567aa961391SAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_DISABLE); 1568aa961391SAlex Deucher } 1569aa961391SAlex Deucher break; 1570aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 1571aa961391SAlex Deucher atombios_ddia_setup(encoder, ATOM_DISABLE); 1572aa961391SAlex Deucher break; 1573aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1574aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1575aa961391SAlex Deucher atombios_external_tmds_setup(encoder, ATOM_DISABLE); 1576aa961391SAlex Deucher break; 1577aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1578aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1579aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1580aa961391SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1581aa961391SAlex Deucher atombios_dac_setup(encoder, ATOM_DISABLE); 15828bf3aae6SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 1583aa961391SAlex Deucher atombios_tv_setup(encoder, ATOM_DISABLE); 1584aa961391SAlex Deucher break; 1585aa961391SAlex Deucher } 1586aa961391SAlex Deucher 1587f28cf339SDave Airlie if (radeon_encoder_is_digital(encoder)) { 15882cd6218cSRafał Miłecki if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 15892cd6218cSRafał Miłecki r600_hdmi_disable(encoder); 1590f28cf339SDave Airlie dig = radeon_encoder->enc_priv; 1591f28cf339SDave Airlie dig->dig_encoder = -1; 1592f28cf339SDave Airlie } 15934ce001abSDave Airlie radeon_encoder->active_device = 0; 15944ce001abSDave Airlie } 15954ce001abSDave Airlie 1596771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 1597771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 1598771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 1599771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 1600771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 1601771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 16024ce001abSDave Airlie .disable = radeon_atom_encoder_disable, 1603771fe6b9SJerome Glisse /* no detect for TMDS/LVDS yet */ 1604771fe6b9SJerome Glisse }; 1605771fe6b9SJerome Glisse 1606771fe6b9SJerome Glisse static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { 1607771fe6b9SJerome Glisse .dpms = radeon_atom_encoder_dpms, 1608771fe6b9SJerome Glisse .mode_fixup = radeon_atom_mode_fixup, 1609771fe6b9SJerome Glisse .prepare = radeon_atom_encoder_prepare, 1610771fe6b9SJerome Glisse .mode_set = radeon_atom_encoder_mode_set, 1611771fe6b9SJerome Glisse .commit = radeon_atom_encoder_commit, 1612771fe6b9SJerome Glisse .detect = radeon_atom_dac_detect, 1613771fe6b9SJerome Glisse }; 1614771fe6b9SJerome Glisse 1615771fe6b9SJerome Glisse void radeon_enc_destroy(struct drm_encoder *encoder) 1616771fe6b9SJerome Glisse { 1617771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1618771fe6b9SJerome Glisse kfree(radeon_encoder->enc_priv); 1619771fe6b9SJerome Glisse drm_encoder_cleanup(encoder); 1620771fe6b9SJerome Glisse kfree(radeon_encoder); 1621771fe6b9SJerome Glisse } 1622771fe6b9SJerome Glisse 1623771fe6b9SJerome Glisse static const struct drm_encoder_funcs radeon_atom_enc_funcs = { 1624771fe6b9SJerome Glisse .destroy = radeon_enc_destroy, 1625771fe6b9SJerome Glisse }; 1626771fe6b9SJerome Glisse 16274ce001abSDave Airlie struct radeon_encoder_atom_dac * 16284ce001abSDave Airlie radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) 16294ce001abSDave Airlie { 1630affd8589SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 1631affd8589SAlex Deucher struct radeon_device *rdev = dev->dev_private; 16324ce001abSDave Airlie struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); 16334ce001abSDave Airlie 16344ce001abSDave Airlie if (!dac) 16354ce001abSDave Airlie return NULL; 16364ce001abSDave Airlie 1637affd8589SAlex Deucher dac->tv_std = radeon_atombios_get_tv_info(rdev); 16384ce001abSDave Airlie return dac; 16394ce001abSDave Airlie } 16404ce001abSDave Airlie 1641771fe6b9SJerome Glisse struct radeon_encoder_atom_dig * 1642771fe6b9SJerome Glisse radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) 1643771fe6b9SJerome Glisse { 1644771fe6b9SJerome Glisse struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); 1645771fe6b9SJerome Glisse 1646771fe6b9SJerome Glisse if (!dig) 1647771fe6b9SJerome Glisse return NULL; 1648771fe6b9SJerome Glisse 1649771fe6b9SJerome Glisse /* coherent mode by default */ 1650771fe6b9SJerome Glisse dig->coherent_mode = true; 1651f28cf339SDave Airlie dig->dig_encoder = -1; 1652771fe6b9SJerome Glisse 1653771fe6b9SJerome Glisse return dig; 1654771fe6b9SJerome Glisse } 1655771fe6b9SJerome Glisse 1656771fe6b9SJerome Glisse void 1657771fe6b9SJerome Glisse radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) 1658771fe6b9SJerome Glisse { 1659dfee5614SDave Airlie struct radeon_device *rdev = dev->dev_private; 1660771fe6b9SJerome Glisse struct drm_encoder *encoder; 1661771fe6b9SJerome Glisse struct radeon_encoder *radeon_encoder; 1662771fe6b9SJerome Glisse 1663771fe6b9SJerome Glisse /* see if we already added it */ 1664771fe6b9SJerome Glisse list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 1665771fe6b9SJerome Glisse radeon_encoder = to_radeon_encoder(encoder); 1666771fe6b9SJerome Glisse if (radeon_encoder->encoder_id == encoder_id) { 1667771fe6b9SJerome Glisse radeon_encoder->devices |= supported_device; 1668771fe6b9SJerome Glisse return; 1669771fe6b9SJerome Glisse } 1670771fe6b9SJerome Glisse 1671771fe6b9SJerome Glisse } 1672771fe6b9SJerome Glisse 1673771fe6b9SJerome Glisse /* add a new one */ 1674771fe6b9SJerome Glisse radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); 1675771fe6b9SJerome Glisse if (!radeon_encoder) 1676771fe6b9SJerome Glisse return; 1677771fe6b9SJerome Glisse 1678771fe6b9SJerome Glisse encoder = &radeon_encoder->base; 1679bcc1c2a1SAlex Deucher switch (rdev->num_crtc) { 1680bcc1c2a1SAlex Deucher case 1: 1681dfee5614SDave Airlie encoder->possible_crtcs = 0x1; 1682bcc1c2a1SAlex Deucher break; 1683bcc1c2a1SAlex Deucher case 2: 1684bcc1c2a1SAlex Deucher default: 1685771fe6b9SJerome Glisse encoder->possible_crtcs = 0x3; 1686bcc1c2a1SAlex Deucher break; 1687bcc1c2a1SAlex Deucher case 6: 1688bcc1c2a1SAlex Deucher encoder->possible_crtcs = 0x3f; 1689bcc1c2a1SAlex Deucher break; 1690bcc1c2a1SAlex Deucher } 1691771fe6b9SJerome Glisse 1692771fe6b9SJerome Glisse radeon_encoder->enc_priv = NULL; 1693771fe6b9SJerome Glisse 1694771fe6b9SJerome Glisse radeon_encoder->encoder_id = encoder_id; 1695771fe6b9SJerome Glisse radeon_encoder->devices = supported_device; 1696c93bb85bSJerome Glisse radeon_encoder->rmx_type = RMX_OFF; 1697771fe6b9SJerome Glisse 1698771fe6b9SJerome Glisse switch (radeon_encoder->encoder_id) { 1699771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1700771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1701771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1702771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1703771fe6b9SJerome Glisse if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1704771fe6b9SJerome Glisse radeon_encoder->rmx_type = RMX_FULL; 1705771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 1706771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 1707771fe6b9SJerome Glisse } else { 1708771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 1709771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 1710771fe6b9SJerome Glisse } 1711771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 1712771fe6b9SJerome Glisse break; 1713771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1714771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); 1715affd8589SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 1716771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 1717771fe6b9SJerome Glisse break; 1718771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1719771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1720771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1721771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); 17224ce001abSDave Airlie radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 1723771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 1724771fe6b9SJerome Glisse break; 1725771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1726771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1727771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_DDI: 1728771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1729771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1730771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1731771fe6b9SJerome Glisse case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 173260d15f55SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 173360d15f55SAlex Deucher radeon_encoder->rmx_type = RMX_FULL; 173460d15f55SAlex Deucher drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); 173560d15f55SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 173660d15f55SAlex Deucher } else { 1737771fe6b9SJerome Glisse drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); 1738771fe6b9SJerome Glisse radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 173960d15f55SAlex Deucher } 1740771fe6b9SJerome Glisse drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 1741771fe6b9SJerome Glisse break; 1742771fe6b9SJerome Glisse } 1743771fe6b9SJerome Glisse } 1744