13f03ced8SAlex Deucher /* 23f03ced8SAlex Deucher * Copyright 2007-11 Advanced Micro Devices, Inc. 33f03ced8SAlex Deucher * Copyright 2008 Red Hat Inc. 43f03ced8SAlex Deucher * 53f03ced8SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a 63f03ced8SAlex Deucher * copy of this software and associated documentation files (the "Software"), 73f03ced8SAlex Deucher * to deal in the Software without restriction, including without limitation 83f03ced8SAlex Deucher * the rights to use, copy, modify, merge, publish, distribute, sublicense, 93f03ced8SAlex Deucher * and/or sell copies of the Software, and to permit persons to whom the 103f03ced8SAlex Deucher * Software is furnished to do so, subject to the following conditions: 113f03ced8SAlex Deucher * 123f03ced8SAlex Deucher * The above copyright notice and this permission notice shall be included in 133f03ced8SAlex Deucher * all copies or substantial portions of the Software. 143f03ced8SAlex Deucher * 153f03ced8SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163f03ced8SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173f03ced8SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 183f03ced8SAlex Deucher * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 193f03ced8SAlex Deucher * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 203f03ced8SAlex Deucher * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 213f03ced8SAlex Deucher * OTHER DEALINGS IN THE SOFTWARE. 223f03ced8SAlex Deucher * 233f03ced8SAlex Deucher * Authors: Dave Airlie 243f03ced8SAlex Deucher * Alex Deucher 253f03ced8SAlex Deucher */ 26c182615fSSam Ravnborg 27f3728734SAlex Deucher #include <linux/backlight.h> 28564d8a2cSMario Kleiner #include <linux/dmi.h> 292ef79416SThomas Zimmermann #include <linux/pci.h> 303f03ced8SAlex Deucher 31c182615fSSam Ravnborg #include <drm/drm_crtc_helper.h> 32c182615fSSam Ravnborg #include <drm/drm_file.h> 33c182615fSSam Ravnborg #include <drm/radeon_drm.h> 34c182615fSSam Ravnborg 35*1eb67781SHans de Goede #include <acpi/video.h> 36*1eb67781SHans de Goede 37c182615fSSam Ravnborg #include "atom.h" 3854ae7f99SLee Jones #include "radeon_atombios.h" 39c182615fSSam Ravnborg #include "radeon.h" 40c182615fSSam Ravnborg #include "radeon_asic.h" 41c182615fSSam Ravnborg #include "radeon_audio.h" 42c182615fSSam Ravnborg 433f03ced8SAlex Deucher extern int atom_debug; 443f03ced8SAlex Deucher 45f3728734SAlex Deucher static u8 46f3728734SAlex Deucher radeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev) 47f3728734SAlex Deucher { 48f3728734SAlex Deucher u8 backlight_level; 49f3728734SAlex Deucher u32 bios_2_scratch; 50f3728734SAlex Deucher 51f3728734SAlex Deucher if (rdev->family >= CHIP_R600) 52f3728734SAlex Deucher bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); 53f3728734SAlex Deucher else 54f3728734SAlex Deucher bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); 55f3728734SAlex Deucher 56f3728734SAlex Deucher backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK) >> 57f3728734SAlex Deucher ATOM_S2_CURRENT_BL_LEVEL_SHIFT); 58f3728734SAlex Deucher 59f3728734SAlex Deucher return backlight_level; 60f3728734SAlex Deucher } 61f3728734SAlex Deucher 62f3728734SAlex Deucher static void 63f3728734SAlex Deucher radeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev, 64f3728734SAlex Deucher u8 backlight_level) 65f3728734SAlex Deucher { 66f3728734SAlex Deucher u32 bios_2_scratch; 67f3728734SAlex Deucher 68f3728734SAlex Deucher if (rdev->family >= CHIP_R600) 69f3728734SAlex Deucher bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); 70f3728734SAlex Deucher else 71f3728734SAlex Deucher bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); 72f3728734SAlex Deucher 73f3728734SAlex Deucher bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; 74f3728734SAlex Deucher bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT) & 75f3728734SAlex Deucher ATOM_S2_CURRENT_BL_LEVEL_MASK); 76f3728734SAlex Deucher 77f3728734SAlex Deucher if (rdev->family >= CHIP_R600) 78f3728734SAlex Deucher WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); 79f3728734SAlex Deucher else 80f3728734SAlex Deucher WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); 81f3728734SAlex Deucher } 82f3728734SAlex Deucher 836d92f81dSAlex Deucher u8 846d92f81dSAlex Deucher atombios_get_backlight_level(struct radeon_encoder *radeon_encoder) 856d92f81dSAlex Deucher { 866d92f81dSAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 876d92f81dSAlex Deucher struct radeon_device *rdev = dev->dev_private; 886d92f81dSAlex Deucher 896d92f81dSAlex Deucher if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 906d92f81dSAlex Deucher return 0; 916d92f81dSAlex Deucher 926d92f81dSAlex Deucher return radeon_atom_get_backlight_level_from_reg(rdev); 936d92f81dSAlex Deucher } 946d92f81dSAlex Deucher 95fda4b25cSLuca Tettamanti void 9637e9b6a6SAlex Deucher atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) 97f3728734SAlex Deucher { 98f3728734SAlex Deucher struct drm_encoder *encoder = &radeon_encoder->base; 99f3728734SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 100f3728734SAlex Deucher struct radeon_device *rdev = dev->dev_private; 101f3728734SAlex Deucher struct radeon_encoder_atom_dig *dig; 102f3728734SAlex Deucher DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 103f3728734SAlex Deucher int index; 104f3728734SAlex Deucher 10537e9b6a6SAlex Deucher if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 10637e9b6a6SAlex Deucher return; 10737e9b6a6SAlex Deucher 10837e9b6a6SAlex Deucher if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 10937e9b6a6SAlex Deucher radeon_encoder->enc_priv) { 110f3728734SAlex Deucher dig = radeon_encoder->enc_priv; 11137e9b6a6SAlex Deucher dig->backlight_level = level; 112f3728734SAlex Deucher radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level); 113f3728734SAlex Deucher 114f3728734SAlex Deucher switch (radeon_encoder->encoder_id) { 115f3728734SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 116f3728734SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 117f3728734SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 118f3728734SAlex Deucher if (dig->backlight_level == 0) { 119f3728734SAlex Deucher args.ucAction = ATOM_LCD_BLOFF; 120f3728734SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 121f3728734SAlex Deucher } else { 122f3728734SAlex Deucher args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL; 123f3728734SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 124f3728734SAlex Deucher args.ucAction = ATOM_LCD_BLON; 125f3728734SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 126f3728734SAlex Deucher } 127f3728734SAlex Deucher break; 128f3728734SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 129f3728734SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 130f3728734SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 131f3728734SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 132d3200be6SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 133f3728734SAlex Deucher if (dig->backlight_level == 0) 134f3728734SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); 135f3728734SAlex Deucher else { 136f3728734SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0); 137f3728734SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); 138f3728734SAlex Deucher } 139f3728734SAlex Deucher break; 140f3728734SAlex Deucher default: 141f3728734SAlex Deucher break; 142f3728734SAlex Deucher } 143f3728734SAlex Deucher } 144f3728734SAlex Deucher } 145f3728734SAlex Deucher 146f3728734SAlex Deucher static u8 radeon_atom_bl_level(struct backlight_device *bd) 147f3728734SAlex Deucher { 148f3728734SAlex Deucher u8 level; 149f3728734SAlex Deucher 150f3728734SAlex Deucher /* Convert brightness to hardware level */ 151f3728734SAlex Deucher if (bd->props.brightness < 0) 152f3728734SAlex Deucher level = 0; 153f3728734SAlex Deucher else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) 154f3728734SAlex Deucher level = RADEON_MAX_BL_LEVEL; 155f3728734SAlex Deucher else 156f3728734SAlex Deucher level = bd->props.brightness; 157f3728734SAlex Deucher 158f3728734SAlex Deucher return level; 159f3728734SAlex Deucher } 160f3728734SAlex Deucher 161f3728734SAlex Deucher static int radeon_atom_backlight_update_status(struct backlight_device *bd) 162f3728734SAlex Deucher { 163f3728734SAlex Deucher struct radeon_backlight_privdata *pdata = bl_get_data(bd); 164f3728734SAlex Deucher struct radeon_encoder *radeon_encoder = pdata->encoder; 165f3728734SAlex Deucher 16637e9b6a6SAlex Deucher atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd)); 167f3728734SAlex Deucher 168f3728734SAlex Deucher return 0; 169f3728734SAlex Deucher } 170f3728734SAlex Deucher 171f3728734SAlex Deucher static int radeon_atom_backlight_get_brightness(struct backlight_device *bd) 172f3728734SAlex Deucher { 173f3728734SAlex Deucher struct radeon_backlight_privdata *pdata = bl_get_data(bd); 174f3728734SAlex Deucher struct radeon_encoder *radeon_encoder = pdata->encoder; 175f3728734SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 176f3728734SAlex Deucher struct radeon_device *rdev = dev->dev_private; 177f3728734SAlex Deucher 178f3728734SAlex Deucher return radeon_atom_get_backlight_level_from_reg(rdev); 179f3728734SAlex Deucher } 180f3728734SAlex Deucher 181f3728734SAlex Deucher static const struct backlight_ops radeon_atom_backlight_ops = { 182f3728734SAlex Deucher .get_brightness = radeon_atom_backlight_get_brightness, 183f3728734SAlex Deucher .update_status = radeon_atom_backlight_update_status, 184f3728734SAlex Deucher }; 185f3728734SAlex Deucher 186f3728734SAlex Deucher void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, 187f3728734SAlex Deucher struct drm_connector *drm_connector) 188f3728734SAlex Deucher { 189f3728734SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 190f3728734SAlex Deucher struct radeon_device *rdev = dev->dev_private; 191f3728734SAlex Deucher struct backlight_device *bd; 192f3728734SAlex Deucher struct backlight_properties props; 193f3728734SAlex Deucher struct radeon_backlight_privdata *pdata; 194f3728734SAlex Deucher struct radeon_encoder_atom_dig *dig; 195614499b4SAlex Deucher char bl_name[16]; 196f3728734SAlex Deucher 19780101790SAlex Deucher /* Mac laptops with multiple GPUs use the gmux driver for backlight 19880101790SAlex Deucher * so don't register a backlight device 19980101790SAlex Deucher */ 20080101790SAlex Deucher if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) && 201364438fdSNicholas Bishop (rdev->pdev->device == 0x6741) && 202364438fdSNicholas Bishop !dmi_match(DMI_PRODUCT_NAME, "iMac12,1")) 20380101790SAlex Deucher return; 20480101790SAlex Deucher 205f3728734SAlex Deucher if (!radeon_encoder->enc_priv) 206f3728734SAlex Deucher return; 207f3728734SAlex Deucher 208f3728734SAlex Deucher if (!rdev->is_atom_bios) 209f3728734SAlex Deucher return; 210f3728734SAlex Deucher 211f3728734SAlex Deucher if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 212f3728734SAlex Deucher return; 213f3728734SAlex Deucher 214*1eb67781SHans de Goede if (!acpi_video_backlight_use_native()) { 215*1eb67781SHans de Goede drm_info(dev, "Skipping radeon atom DIG backlight registration\n"); 216*1eb67781SHans de Goede return; 217*1eb67781SHans de Goede } 218*1eb67781SHans de Goede 219f3728734SAlex Deucher pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL); 220f3728734SAlex Deucher if (!pdata) { 221f3728734SAlex Deucher DRM_ERROR("Memory allocation failed\n"); 222f3728734SAlex Deucher goto error; 223f3728734SAlex Deucher } 224f3728734SAlex Deucher 225f3728734SAlex Deucher memset(&props, 0, sizeof(props)); 226f3728734SAlex Deucher props.max_brightness = RADEON_MAX_BL_LEVEL; 227f3728734SAlex Deucher props.type = BACKLIGHT_RAW; 228614499b4SAlex Deucher snprintf(bl_name, sizeof(bl_name), 229614499b4SAlex Deucher "radeon_bl%d", dev->primary->index); 2305bdebb18SDave Airlie bd = backlight_device_register(bl_name, drm_connector->kdev, 231f3728734SAlex Deucher pdata, &radeon_atom_backlight_ops, &props); 232f3728734SAlex Deucher if (IS_ERR(bd)) { 233f3728734SAlex Deucher DRM_ERROR("Backlight registration failed\n"); 234f3728734SAlex Deucher goto error; 235f3728734SAlex Deucher } 236f3728734SAlex Deucher 237f3728734SAlex Deucher pdata->encoder = radeon_encoder; 238f3728734SAlex Deucher 239f3728734SAlex Deucher dig = radeon_encoder->enc_priv; 240f3728734SAlex Deucher dig->bl_dev = bd; 241f3728734SAlex Deucher 242f3728734SAlex Deucher bd->props.brightness = radeon_atom_backlight_get_brightness(bd); 243201bb624SAlex Deucher /* Set a reasonable default here if the level is 0 otherwise 244201bb624SAlex Deucher * fbdev will attempt to turn the backlight on after console 245201bb624SAlex Deucher * unblanking and it will try and restore 0 which turns the backlight 246201bb624SAlex Deucher * off again. 247201bb624SAlex Deucher */ 248201bb624SAlex Deucher if (bd->props.brightness == 0) 249201bb624SAlex Deucher bd->props.brightness = RADEON_MAX_BL_LEVEL; 250f3728734SAlex Deucher bd->props.power = FB_BLANK_UNBLANK; 251f3728734SAlex Deucher backlight_update_status(bd); 252f3728734SAlex Deucher 253f3728734SAlex Deucher DRM_INFO("radeon atom DIG backlight initialized\n"); 2544cee6a90SAlex Deucher rdev->mode_info.bl_encoder = radeon_encoder; 255f3728734SAlex Deucher 256f3728734SAlex Deucher return; 257f3728734SAlex Deucher 258f3728734SAlex Deucher error: 259f3728734SAlex Deucher kfree(pdata); 260f3728734SAlex Deucher return; 261f3728734SAlex Deucher } 262f3728734SAlex Deucher 263f3728734SAlex Deucher static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder) 264f3728734SAlex Deucher { 265f3728734SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 266f3728734SAlex Deucher struct radeon_device *rdev = dev->dev_private; 267f3728734SAlex Deucher struct backlight_device *bd = NULL; 268f3728734SAlex Deucher struct radeon_encoder_atom_dig *dig; 269f3728734SAlex Deucher 270f3728734SAlex Deucher if (!radeon_encoder->enc_priv) 271f3728734SAlex Deucher return; 272f3728734SAlex Deucher 273f3728734SAlex Deucher if (!rdev->is_atom_bios) 274f3728734SAlex Deucher return; 275f3728734SAlex Deucher 276f3728734SAlex Deucher if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) 277f3728734SAlex Deucher return; 278f3728734SAlex Deucher 279f3728734SAlex Deucher dig = radeon_encoder->enc_priv; 280f3728734SAlex Deucher bd = dig->bl_dev; 281f3728734SAlex Deucher dig->bl_dev = NULL; 282f3728734SAlex Deucher 283f3728734SAlex Deucher if (bd) { 284f3728734SAlex Deucher struct radeon_legacy_backlight_privdata *pdata; 285f3728734SAlex Deucher 286f3728734SAlex Deucher pdata = bl_get_data(bd); 287f3728734SAlex Deucher backlight_device_unregister(bd); 288f3728734SAlex Deucher kfree(pdata); 289f3728734SAlex Deucher 290f3728734SAlex Deucher DRM_INFO("radeon atom LVDS backlight unloaded\n"); 291f3728734SAlex Deucher } 292f3728734SAlex Deucher } 293f3728734SAlex Deucher 2943f03ced8SAlex Deucher static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, 295e811f5aeSLaurent Pinchart const struct drm_display_mode *mode, 2963f03ced8SAlex Deucher struct drm_display_mode *adjusted_mode) 2973f03ced8SAlex Deucher { 2983f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2993f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 3003f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 3013f03ced8SAlex Deucher 3023f03ced8SAlex Deucher /* set the active encoder to connector routing */ 3033f03ced8SAlex Deucher radeon_encoder_set_active_device(encoder); 3043f03ced8SAlex Deucher drm_mode_set_crtcinfo(adjusted_mode, 0); 3053f03ced8SAlex Deucher 3063f03ced8SAlex Deucher /* hw bug */ 3073f03ced8SAlex Deucher if ((mode->flags & DRM_MODE_FLAG_INTERLACE) 3083f03ced8SAlex Deucher && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) 3093f03ced8SAlex Deucher adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; 3103f03ced8SAlex Deucher 3113104b812SAlex Deucher /* vertical FP must be at least 1 */ 3123104b812SAlex Deucher if (mode->crtc_vsync_start == mode->crtc_vdisplay) 3133104b812SAlex Deucher adjusted_mode->crtc_vsync_start++; 3143104b812SAlex Deucher 315da997620SAlex Deucher /* get the native mode for scaling */ 316da997620SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 3173f03ced8SAlex Deucher radeon_panel_mode_fixup(encoder, adjusted_mode); 318da997620SAlex Deucher } else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) { 3193f03ced8SAlex Deucher struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; 3203f03ced8SAlex Deucher if (tv_dac) { 3213f03ced8SAlex Deucher if (tv_dac->tv_std == TV_STD_NTSC || 3223f03ced8SAlex Deucher tv_dac->tv_std == TV_STD_NTSC_J || 3233f03ced8SAlex Deucher tv_dac->tv_std == TV_STD_PAL_M) 3243f03ced8SAlex Deucher radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); 3253f03ced8SAlex Deucher else 3263f03ced8SAlex Deucher radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); 3273f03ced8SAlex Deucher } 328da997620SAlex Deucher } else if (radeon_encoder->rmx_type != RMX_OFF) { 329da997620SAlex Deucher radeon_panel_mode_fixup(encoder, adjusted_mode); 3303f03ced8SAlex Deucher } 3313f03ced8SAlex Deucher 3323f03ced8SAlex Deucher if (ASIC_IS_DCE3(rdev) && 3333f03ced8SAlex Deucher ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || 3343f03ced8SAlex Deucher (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { 3353f03ced8SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 33693927f9cSAlex Deucher radeon_dp_set_link_config(connector, adjusted_mode); 3373f03ced8SAlex Deucher } 3383f03ced8SAlex Deucher 3393f03ced8SAlex Deucher return true; 3403f03ced8SAlex Deucher } 3413f03ced8SAlex Deucher 3423f03ced8SAlex Deucher static void 3433f03ced8SAlex Deucher atombios_dac_setup(struct drm_encoder *encoder, int action) 3443f03ced8SAlex Deucher { 3453f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 3463f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 3473f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 3483f03ced8SAlex Deucher DAC_ENCODER_CONTROL_PS_ALLOCATION args; 3493f03ced8SAlex Deucher int index = 0; 3503f03ced8SAlex Deucher struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 3513f03ced8SAlex Deucher 3523f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 3533f03ced8SAlex Deucher 3543f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 3553f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 3563f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 3573f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 3583f03ced8SAlex Deucher break; 3593f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 3603f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 3613f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 3623f03ced8SAlex Deucher break; 3633f03ced8SAlex Deucher } 3643f03ced8SAlex Deucher 3653f03ced8SAlex Deucher args.ucAction = action; 3663f03ced8SAlex Deucher 3673f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) 3683f03ced8SAlex Deucher args.ucDacStandard = ATOM_DAC1_PS2; 3693f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 3703f03ced8SAlex Deucher args.ucDacStandard = ATOM_DAC1_CV; 3713f03ced8SAlex Deucher else { 3723f03ced8SAlex Deucher switch (dac_info->tv_std) { 3733f03ced8SAlex Deucher case TV_STD_PAL: 3743f03ced8SAlex Deucher case TV_STD_PAL_M: 3753f03ced8SAlex Deucher case TV_STD_SCART_PAL: 3763f03ced8SAlex Deucher case TV_STD_SECAM: 3773f03ced8SAlex Deucher case TV_STD_PAL_CN: 3783f03ced8SAlex Deucher args.ucDacStandard = ATOM_DAC1_PAL; 3793f03ced8SAlex Deucher break; 3803f03ced8SAlex Deucher case TV_STD_NTSC: 3813f03ced8SAlex Deucher case TV_STD_NTSC_J: 3823f03ced8SAlex Deucher case TV_STD_PAL_60: 3833f03ced8SAlex Deucher default: 3843f03ced8SAlex Deucher args.ucDacStandard = ATOM_DAC1_NTSC; 3853f03ced8SAlex Deucher break; 3863f03ced8SAlex Deucher } 3873f03ced8SAlex Deucher } 3883f03ced8SAlex Deucher args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 3893f03ced8SAlex Deucher 3903f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 3913f03ced8SAlex Deucher 3923f03ced8SAlex Deucher } 3933f03ced8SAlex Deucher 3943f03ced8SAlex Deucher static void 3953f03ced8SAlex Deucher atombios_tv_setup(struct drm_encoder *encoder, int action) 3963f03ced8SAlex Deucher { 3973f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 3983f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 3993f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 4003f03ced8SAlex Deucher TV_ENCODER_CONTROL_PS_ALLOCATION args; 4013f03ced8SAlex Deucher int index = 0; 4023f03ced8SAlex Deucher struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; 4033f03ced8SAlex Deucher 4043f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 4053f03ced8SAlex Deucher 4063f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 4073f03ced8SAlex Deucher 4083f03ced8SAlex Deucher args.sTVEncoder.ucAction = action; 4093f03ced8SAlex Deucher 4103f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 4113f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 4123f03ced8SAlex Deucher else { 4133f03ced8SAlex Deucher switch (dac_info->tv_std) { 4143f03ced8SAlex Deucher case TV_STD_NTSC: 4153f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 4163f03ced8SAlex Deucher break; 4173f03ced8SAlex Deucher case TV_STD_PAL: 4183f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; 4193f03ced8SAlex Deucher break; 4203f03ced8SAlex Deucher case TV_STD_PAL_M: 4213f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; 4223f03ced8SAlex Deucher break; 4233f03ced8SAlex Deucher case TV_STD_PAL_60: 4243f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; 4253f03ced8SAlex Deucher break; 4263f03ced8SAlex Deucher case TV_STD_NTSC_J: 4273f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; 4283f03ced8SAlex Deucher break; 4293f03ced8SAlex Deucher case TV_STD_SCART_PAL: 4303f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ 4313f03ced8SAlex Deucher break; 4323f03ced8SAlex Deucher case TV_STD_SECAM: 4333f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; 4343f03ced8SAlex Deucher break; 4353f03ced8SAlex Deucher case TV_STD_PAL_CN: 4363f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; 4373f03ced8SAlex Deucher break; 4383f03ced8SAlex Deucher default: 4393f03ced8SAlex Deucher args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 4403f03ced8SAlex Deucher break; 4413f03ced8SAlex Deucher } 4423f03ced8SAlex Deucher } 4433f03ced8SAlex Deucher 4443f03ced8SAlex Deucher args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 4453f03ced8SAlex Deucher 4463f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 4473f03ced8SAlex Deucher 4483f03ced8SAlex Deucher } 4493f03ced8SAlex Deucher 4501f0e2943SAlex Deucher static u8 radeon_atom_get_bpc(struct drm_encoder *encoder) 4511f0e2943SAlex Deucher { 4521f0e2943SAlex Deucher int bpc = 8; 4531f0e2943SAlex Deucher 4547d5a33b0SAlex Deucher if (encoder->crtc) { 4557d5a33b0SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 4567d5a33b0SAlex Deucher bpc = radeon_crtc->bpc; 4577d5a33b0SAlex Deucher } 4581f0e2943SAlex Deucher 4591f0e2943SAlex Deucher switch (bpc) { 4601f0e2943SAlex Deucher case 0: 4611f0e2943SAlex Deucher return PANEL_BPC_UNDEFINE; 4621f0e2943SAlex Deucher case 6: 4631f0e2943SAlex Deucher return PANEL_6BIT_PER_COLOR; 4641f0e2943SAlex Deucher case 8: 4651f0e2943SAlex Deucher default: 4661f0e2943SAlex Deucher return PANEL_8BIT_PER_COLOR; 4671f0e2943SAlex Deucher case 10: 4681f0e2943SAlex Deucher return PANEL_10BIT_PER_COLOR; 4691f0e2943SAlex Deucher case 12: 4701f0e2943SAlex Deucher return PANEL_12BIT_PER_COLOR; 4711f0e2943SAlex Deucher case 16: 4721f0e2943SAlex Deucher return PANEL_16BIT_PER_COLOR; 4731f0e2943SAlex Deucher } 4741f0e2943SAlex Deucher } 4751f0e2943SAlex Deucher 4763f03ced8SAlex Deucher union dvo_encoder_control { 4773f03ced8SAlex Deucher ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds; 4783f03ced8SAlex Deucher DVO_ENCODER_CONTROL_PS_ALLOCATION dvo; 4793f03ced8SAlex Deucher DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3; 480aea65641SAlex Deucher DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4 dvo_v4; 4813f03ced8SAlex Deucher }; 4823f03ced8SAlex Deucher 4833f03ced8SAlex Deucher void 4843f03ced8SAlex Deucher atombios_dvo_setup(struct drm_encoder *encoder, int action) 4853f03ced8SAlex Deucher { 4863f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 4873f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 4883f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 4893f03ced8SAlex Deucher union dvo_encoder_control args; 4903f03ced8SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); 49124153dd3SAlex Deucher uint8_t frev, crev; 4923f03ced8SAlex Deucher 4933f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 4943f03ced8SAlex Deucher 49524153dd3SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 49624153dd3SAlex Deucher return; 49724153dd3SAlex Deucher 498afceb931SAlex Deucher /* some R4xx chips have the wrong frev */ 499afceb931SAlex Deucher if (rdev->family <= CHIP_RV410) 500afceb931SAlex Deucher frev = 1; 501afceb931SAlex Deucher 50224153dd3SAlex Deucher switch (frev) { 50324153dd3SAlex Deucher case 1: 50424153dd3SAlex Deucher switch (crev) { 50524153dd3SAlex Deucher case 1: 50624153dd3SAlex Deucher /* R4xx, R5xx */ 50724153dd3SAlex Deucher args.ext_tmds.sXTmdsEncoder.ucEnable = action; 50824153dd3SAlex Deucher 5099aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 51024153dd3SAlex Deucher args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; 51124153dd3SAlex Deucher 51224153dd3SAlex Deucher args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; 51324153dd3SAlex Deucher break; 51424153dd3SAlex Deucher case 2: 51524153dd3SAlex Deucher /* RS600/690/740 */ 5163f03ced8SAlex Deucher args.dvo.sDVOEncoder.ucAction = action; 5173f03ced8SAlex Deucher args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 5183f03ced8SAlex Deucher /* DFP1, CRT1, TV1 depending on the type of port */ 5193f03ced8SAlex Deucher args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; 5203f03ced8SAlex Deucher 5219aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 5223f03ced8SAlex Deucher args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; 52324153dd3SAlex Deucher break; 52424153dd3SAlex Deucher case 3: 52524153dd3SAlex Deucher /* R6xx */ 52624153dd3SAlex Deucher args.dvo_v3.ucAction = action; 52724153dd3SAlex Deucher args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 52824153dd3SAlex Deucher args.dvo_v3.ucDVOConfig = 0; /* XXX */ 52924153dd3SAlex Deucher break; 530aea65641SAlex Deucher case 4: 531aea65641SAlex Deucher /* DCE8 */ 532aea65641SAlex Deucher args.dvo_v4.ucAction = action; 533aea65641SAlex Deucher args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 534aea65641SAlex Deucher args.dvo_v4.ucDVOConfig = 0; /* XXX */ 535aea65641SAlex Deucher args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder); 536aea65641SAlex Deucher break; 53724153dd3SAlex Deucher default: 53824153dd3SAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 53924153dd3SAlex Deucher break; 54024153dd3SAlex Deucher } 54124153dd3SAlex Deucher break; 54224153dd3SAlex Deucher default: 54324153dd3SAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 54424153dd3SAlex Deucher break; 5453f03ced8SAlex Deucher } 5463f03ced8SAlex Deucher 5473f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 5483f03ced8SAlex Deucher } 5493f03ced8SAlex Deucher 5503f03ced8SAlex Deucher union lvds_encoder_control { 5513f03ced8SAlex Deucher LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 5523f03ced8SAlex Deucher LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 5533f03ced8SAlex Deucher }; 5543f03ced8SAlex Deucher 5553f03ced8SAlex Deucher void 5563f03ced8SAlex Deucher atombios_digital_setup(struct drm_encoder *encoder, int action) 5573f03ced8SAlex Deucher { 5583f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 5593f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 5603f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 5613f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 5623f03ced8SAlex Deucher union lvds_encoder_control args; 5633f03ced8SAlex Deucher int index = 0; 5643f03ced8SAlex Deucher int hdmi_detected = 0; 5653f03ced8SAlex Deucher uint8_t frev, crev; 5663f03ced8SAlex Deucher 5673f03ced8SAlex Deucher if (!dig) 5683f03ced8SAlex Deucher return; 5693f03ced8SAlex Deucher 5703f03ced8SAlex Deucher if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) 5713f03ced8SAlex Deucher hdmi_detected = 1; 5723f03ced8SAlex Deucher 5733f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 5743f03ced8SAlex Deucher 5753f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 5763f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 5773f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 5783f03ced8SAlex Deucher break; 5793f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 5803f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 5813f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 5823f03ced8SAlex Deucher break; 5833f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 5843f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 5853f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 5863f03ced8SAlex Deucher else 5873f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 5883f03ced8SAlex Deucher break; 5893f03ced8SAlex Deucher } 5903f03ced8SAlex Deucher 5913f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 5923f03ced8SAlex Deucher return; 5933f03ced8SAlex Deucher 5943f03ced8SAlex Deucher switch (frev) { 5953f03ced8SAlex Deucher case 1: 5963f03ced8SAlex Deucher case 2: 5973f03ced8SAlex Deucher switch (crev) { 5983f03ced8SAlex Deucher case 1: 5993f03ced8SAlex Deucher args.v1.ucMisc = 0; 6003f03ced8SAlex Deucher args.v1.ucAction = action; 6013f03ced8SAlex Deucher if (hdmi_detected) 6023f03ced8SAlex Deucher args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 6033f03ced8SAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 6043f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 6053f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 6063f03ced8SAlex Deucher args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 6073f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 6083f03ced8SAlex Deucher args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 6093f03ced8SAlex Deucher } else { 6103f03ced8SAlex Deucher if (dig->linkb) 6113f03ced8SAlex Deucher args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 6129aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 6133f03ced8SAlex Deucher args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 6143f03ced8SAlex Deucher /*if (pScrn->rgbBits == 8) */ 6153f03ced8SAlex Deucher args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 6163f03ced8SAlex Deucher } 6173f03ced8SAlex Deucher break; 6183f03ced8SAlex Deucher case 2: 6193f03ced8SAlex Deucher case 3: 6203f03ced8SAlex Deucher args.v2.ucMisc = 0; 6213f03ced8SAlex Deucher args.v2.ucAction = action; 6223f03ced8SAlex Deucher if (crev == 3) { 6233f03ced8SAlex Deucher if (dig->coherent_mode) 6243f03ced8SAlex Deucher args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 6253f03ced8SAlex Deucher } 6263f03ced8SAlex Deucher if (hdmi_detected) 6273f03ced8SAlex Deucher args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 6283f03ced8SAlex Deucher args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 6293f03ced8SAlex Deucher args.v2.ucTruncate = 0; 6303f03ced8SAlex Deucher args.v2.ucSpatial = 0; 6313f03ced8SAlex Deucher args.v2.ucTemporal = 0; 6323f03ced8SAlex Deucher args.v2.ucFRC = 0; 6333f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 6343f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 6353f03ced8SAlex Deucher args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 6363f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { 6373f03ced8SAlex Deucher args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 6383f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 6393f03ced8SAlex Deucher args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 6403f03ced8SAlex Deucher } 6413f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { 6423f03ced8SAlex Deucher args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 6433f03ced8SAlex Deucher if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 6443f03ced8SAlex Deucher args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 6453f03ced8SAlex Deucher if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) 6463f03ced8SAlex Deucher args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 6473f03ced8SAlex Deucher } 6483f03ced8SAlex Deucher } else { 6493f03ced8SAlex Deucher if (dig->linkb) 6503f03ced8SAlex Deucher args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 6519aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 6523f03ced8SAlex Deucher args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 6533f03ced8SAlex Deucher } 6543f03ced8SAlex Deucher break; 6553f03ced8SAlex Deucher default: 6563f03ced8SAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 6573f03ced8SAlex Deucher break; 6583f03ced8SAlex Deucher } 6593f03ced8SAlex Deucher break; 6603f03ced8SAlex Deucher default: 6613f03ced8SAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 6623f03ced8SAlex Deucher break; 6633f03ced8SAlex Deucher } 6643f03ced8SAlex Deucher 6653f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 6663f03ced8SAlex Deucher } 6673f03ced8SAlex Deucher 6683f03ced8SAlex Deucher int 6693f03ced8SAlex Deucher atombios_get_encoder_mode(struct drm_encoder *encoder) 6703f03ced8SAlex Deucher { 671e55bca26SSlava Grigorev struct drm_device *dev = encoder->dev; 672e55bca26SSlava Grigorev struct radeon_device *rdev = dev->dev_private; 6733f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 6743f03ced8SAlex Deucher struct drm_connector *connector; 6753f03ced8SAlex Deucher struct radeon_connector *radeon_connector; 6763f03ced8SAlex Deucher struct radeon_connector_atom_dig *dig_connector; 6779843ead0SDave Airlie struct radeon_encoder_atom_dig *dig_enc; 6783f03ced8SAlex Deucher 6799843ead0SDave Airlie if (radeon_encoder_is_digital(encoder)) { 6809843ead0SDave Airlie dig_enc = radeon_encoder->enc_priv; 6819843ead0SDave Airlie if (dig_enc->active_mst_links) 6829843ead0SDave Airlie return ATOM_ENCODER_MODE_DP_MST; 6839843ead0SDave Airlie } 6849843ead0SDave Airlie if (radeon_encoder->is_mst_encoder || radeon_encoder->offset) 6859843ead0SDave Airlie return ATOM_ENCODER_MODE_DP_MST; 6863f03ced8SAlex Deucher /* dp bridges are always DP */ 6873f03ced8SAlex Deucher if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) 6883f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DP; 6893f03ced8SAlex Deucher 6903f03ced8SAlex Deucher /* DVO is always DVO */ 691a59fbb8eSAlex Deucher if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO1) || 692a59fbb8eSAlex Deucher (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) 6933f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DVO; 6943f03ced8SAlex Deucher 6953f03ced8SAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 6963f03ced8SAlex Deucher /* if we don't have an active device yet, just use one of 6973f03ced8SAlex Deucher * the connectors tied to the encoder. 6983f03ced8SAlex Deucher */ 6993f03ced8SAlex Deucher if (!connector) 7003f03ced8SAlex Deucher connector = radeon_get_connector_for_encoder_init(encoder); 7013f03ced8SAlex Deucher radeon_connector = to_radeon_connector(connector); 7023f03ced8SAlex Deucher 7033f03ced8SAlex Deucher switch (connector->connector_type) { 7043f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_DVII: 7053f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ 706108dc8e8SAlex Deucher if (radeon_audio != 0) { 707108dc8e8SAlex Deucher if (radeon_connector->use_digital && 708108dc8e8SAlex Deucher (radeon_connector->audio == RADEON_AUDIO_ENABLE)) 709108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 710377bd8a9SAlex Deucher else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && 711108dc8e8SAlex Deucher (radeon_connector->audio == RADEON_AUDIO_AUTO)) 7123f03ced8SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 713f92e70caSRafał Miłecki else if (radeon_connector->use_digital) 7143f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DVI; 7153f03ced8SAlex Deucher else 7163f03ced8SAlex Deucher return ATOM_ENCODER_MODE_CRT; 717108dc8e8SAlex Deucher } else if (radeon_connector->use_digital) { 718108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_DVI; 719108dc8e8SAlex Deucher } else { 720108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_CRT; 721108dc8e8SAlex Deucher } 7223f03ced8SAlex Deucher break; 7233f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_DVID: 7243f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_HDMIA: 7253f03ced8SAlex Deucher default: 726108dc8e8SAlex Deucher if (radeon_audio != 0) { 727108dc8e8SAlex Deucher if (radeon_connector->audio == RADEON_AUDIO_ENABLE) 728108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 729377bd8a9SAlex Deucher else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && 730108dc8e8SAlex Deucher (radeon_connector->audio == RADEON_AUDIO_AUTO)) 7313f03ced8SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 732f92e70caSRafał Miłecki else 7333f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DVI; 734108dc8e8SAlex Deucher } else { 735108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_DVI; 736108dc8e8SAlex Deucher } 7373f03ced8SAlex Deucher break; 7383f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_LVDS: 7393f03ced8SAlex Deucher return ATOM_ENCODER_MODE_LVDS; 7403f03ced8SAlex Deucher break; 7413f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_DisplayPort: 7423f03ced8SAlex Deucher dig_connector = radeon_connector->con_priv; 7433f03ced8SAlex Deucher if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 744108dc8e8SAlex Deucher (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { 7453473f542SAlex Deucher if (radeon_audio != 0 && 7463473f542SAlex Deucher drm_detect_monitor_audio(radeon_connector_edid(connector)) && 7473473f542SAlex Deucher ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev)) 748e55bca26SSlava Grigorev return ATOM_ENCODER_MODE_DP_AUDIO; 7493f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DP; 750108dc8e8SAlex Deucher } else if (radeon_audio != 0) { 751108dc8e8SAlex Deucher if (radeon_connector->audio == RADEON_AUDIO_ENABLE) 752108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 753377bd8a9SAlex Deucher else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && 754108dc8e8SAlex Deucher (radeon_connector->audio == RADEON_AUDIO_AUTO)) 7553f03ced8SAlex Deucher return ATOM_ENCODER_MODE_HDMI; 756f92e70caSRafał Miłecki else 7573f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DVI; 758108dc8e8SAlex Deucher } else { 759108dc8e8SAlex Deucher return ATOM_ENCODER_MODE_DVI; 760108dc8e8SAlex Deucher } 7613f03ced8SAlex Deucher break; 7623f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_eDP: 7633473f542SAlex Deucher if (radeon_audio != 0 && 7643473f542SAlex Deucher drm_detect_monitor_audio(radeon_connector_edid(connector)) && 7653473f542SAlex Deucher ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev)) 766e55bca26SSlava Grigorev return ATOM_ENCODER_MODE_DP_AUDIO; 7673f03ced8SAlex Deucher return ATOM_ENCODER_MODE_DP; 7683f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_DVIA: 7693f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_VGA: 7703f03ced8SAlex Deucher return ATOM_ENCODER_MODE_CRT; 7713f03ced8SAlex Deucher break; 7723f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_Composite: 7733f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_SVIDEO: 7743f03ced8SAlex Deucher case DRM_MODE_CONNECTOR_9PinDIN: 7753f03ced8SAlex Deucher /* fix me */ 7763f03ced8SAlex Deucher return ATOM_ENCODER_MODE_TV; 7773f03ced8SAlex Deucher /*return ATOM_ENCODER_MODE_CV;*/ 7783f03ced8SAlex Deucher break; 7793f03ced8SAlex Deucher } 7803f03ced8SAlex Deucher } 7813f03ced8SAlex Deucher 7823f03ced8SAlex Deucher /* 7833f03ced8SAlex Deucher * DIG Encoder/Transmitter Setup 7843f03ced8SAlex Deucher * 7853f03ced8SAlex Deucher * DCE 3.0/3.1 7863f03ced8SAlex Deucher * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. 7873f03ced8SAlex Deucher * Supports up to 3 digital outputs 7883f03ced8SAlex Deucher * - 2 DIG encoder blocks. 7893f03ced8SAlex Deucher * DIG1 can drive UNIPHY link A or link B 7903f03ced8SAlex Deucher * DIG2 can drive UNIPHY link B or LVTMA 7913f03ced8SAlex Deucher * 7923f03ced8SAlex Deucher * DCE 3.2 7933f03ced8SAlex Deucher * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). 7943f03ced8SAlex Deucher * Supports up to 5 digital outputs 7953f03ced8SAlex Deucher * - 2 DIG encoder blocks. 7963f03ced8SAlex Deucher * DIG1/2 can drive UNIPHY0/1/2 link A or link B 7973f03ced8SAlex Deucher * 7982d415869SAlex Deucher * DCE 4.0/5.0/6.0 7993f03ced8SAlex Deucher * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). 8003f03ced8SAlex Deucher * Supports up to 6 digital outputs 8013f03ced8SAlex Deucher * - 6 DIG encoder blocks. 8023f03ced8SAlex Deucher * - DIG to PHY mapping is hardcoded 8033f03ced8SAlex Deucher * DIG1 drives UNIPHY0 link A, A+B 8043f03ced8SAlex Deucher * DIG2 drives UNIPHY0 link B 8053f03ced8SAlex Deucher * DIG3 drives UNIPHY1 link A, A+B 8063f03ced8SAlex Deucher * DIG4 drives UNIPHY1 link B 8073f03ced8SAlex Deucher * DIG5 drives UNIPHY2 link A, A+B 8083f03ced8SAlex Deucher * DIG6 drives UNIPHY2 link B 8093f03ced8SAlex Deucher * 8103f03ced8SAlex Deucher * DCE 4.1 8113f03ced8SAlex Deucher * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). 8123f03ced8SAlex Deucher * Supports up to 6 digital outputs 8133f03ced8SAlex Deucher * - 2 DIG encoder blocks. 8142d415869SAlex Deucher * llano 8153f03ced8SAlex Deucher * DIG1/2 can drive UNIPHY0/1/2 link A or link B 8162d415869SAlex Deucher * ontario 8172d415869SAlex Deucher * DIG1 drives UNIPHY0/1/2 link A 8182d415869SAlex Deucher * DIG2 drives UNIPHY0/1/2 link B 8193f03ced8SAlex Deucher * 8203f03ced8SAlex Deucher * Routing 8213f03ced8SAlex Deucher * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) 8223f03ced8SAlex Deucher * Examples: 8233f03ced8SAlex Deucher * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI 8243f03ced8SAlex Deucher * crtc1 -> dig1 -> UNIPHY0 link B -> DP 8253f03ced8SAlex Deucher * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS 8263f03ced8SAlex Deucher * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI 8273f03ced8SAlex Deucher */ 8283f03ced8SAlex Deucher 8293f03ced8SAlex Deucher union dig_encoder_control { 8303f03ced8SAlex Deucher DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 8313f03ced8SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 8323f03ced8SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 8333f03ced8SAlex Deucher DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 8343f03ced8SAlex Deucher }; 8353f03ced8SAlex Deucher 8363f03ced8SAlex Deucher void 837bf071900SDave Airlie atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override) 8383f03ced8SAlex Deucher { 8393f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 8403f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 8413f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 8423f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 8433f03ced8SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 8443f03ced8SAlex Deucher union dig_encoder_control args; 8453f03ced8SAlex Deucher int index = 0; 8463f03ced8SAlex Deucher uint8_t frev, crev; 8473f03ced8SAlex Deucher int dp_clock = 0; 8483f03ced8SAlex Deucher int dp_lane_count = 0; 8493f03ced8SAlex Deucher int hpd_id = RADEON_HPD_NONE; 8503f03ced8SAlex Deucher 8513f03ced8SAlex Deucher if (connector) { 8523f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 8533f03ced8SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 8543f03ced8SAlex Deucher radeon_connector->con_priv; 8553f03ced8SAlex Deucher 8563f03ced8SAlex Deucher dp_clock = dig_connector->dp_clock; 8573f03ced8SAlex Deucher dp_lane_count = dig_connector->dp_lane_count; 8583f03ced8SAlex Deucher hpd_id = radeon_connector->hpd.hpd; 8593f03ced8SAlex Deucher } 8603f03ced8SAlex Deucher 8613f03ced8SAlex Deucher /* no dig encoder assigned */ 8623f03ced8SAlex Deucher if (dig->dig_encoder == -1) 8633f03ced8SAlex Deucher return; 8643f03ced8SAlex Deucher 8653f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 8663f03ced8SAlex Deucher 8673f03ced8SAlex Deucher if (ASIC_IS_DCE4(rdev)) 8683f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 8693f03ced8SAlex Deucher else { 8703f03ced8SAlex Deucher if (dig->dig_encoder) 8713f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 8723f03ced8SAlex Deucher else 8733f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 8743f03ced8SAlex Deucher } 8753f03ced8SAlex Deucher 8763f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 8773f03ced8SAlex Deucher return; 8783f03ced8SAlex Deucher 87958cdcb8bSAlex Deucher switch (frev) { 88058cdcb8bSAlex Deucher case 1: 88158cdcb8bSAlex Deucher switch (crev) { 88258cdcb8bSAlex Deucher case 1: 8833f03ced8SAlex Deucher args.v1.ucAction = action; 8843f03ced8SAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 8853f03ced8SAlex Deucher if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 8863f03ced8SAlex Deucher args.v3.ucPanelMode = panel_mode; 8873f03ced8SAlex Deucher else 8883f03ced8SAlex Deucher args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); 8893f03ced8SAlex Deucher 8903f03ced8SAlex Deucher if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) 8913f03ced8SAlex Deucher args.v1.ucLaneNum = dp_lane_count; 8929aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 8933f03ced8SAlex Deucher args.v1.ucLaneNum = 8; 8943f03ced8SAlex Deucher else 8953f03ced8SAlex Deucher args.v1.ucLaneNum = 4; 8963f03ced8SAlex Deucher 89758cdcb8bSAlex Deucher switch (radeon_encoder->encoder_id) { 89858cdcb8bSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 89958cdcb8bSAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 90058cdcb8bSAlex Deucher break; 90158cdcb8bSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 90258cdcb8bSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 90358cdcb8bSAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 90458cdcb8bSAlex Deucher break; 90558cdcb8bSAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 90658cdcb8bSAlex Deucher args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 90758cdcb8bSAlex Deucher break; 90858cdcb8bSAlex Deucher } 90958cdcb8bSAlex Deucher if (dig->linkb) 91058cdcb8bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 91158cdcb8bSAlex Deucher else 91258cdcb8bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 913459ee1c3SMario Kleiner 914459ee1c3SMario Kleiner if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000)) 915459ee1c3SMario Kleiner args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 916459ee1c3SMario Kleiner 91758cdcb8bSAlex Deucher break; 91858cdcb8bSAlex Deucher case 2: 91958cdcb8bSAlex Deucher case 3: 92058cdcb8bSAlex Deucher args.v3.ucAction = action; 92158cdcb8bSAlex Deucher args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 92258cdcb8bSAlex Deucher if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 92358cdcb8bSAlex Deucher args.v3.ucPanelMode = panel_mode; 92458cdcb8bSAlex Deucher else 92558cdcb8bSAlex Deucher args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder); 92658cdcb8bSAlex Deucher 9272f6fa79aSAlex Deucher if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode)) 92858cdcb8bSAlex Deucher args.v3.ucLaneNum = dp_lane_count; 9299aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 93058cdcb8bSAlex Deucher args.v3.ucLaneNum = 8; 93158cdcb8bSAlex Deucher else 93258cdcb8bSAlex Deucher args.v3.ucLaneNum = 4; 93358cdcb8bSAlex Deucher 9342f6fa79aSAlex Deucher if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000)) 93558cdcb8bSAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 936bf071900SDave Airlie if (enc_override != -1) 937bf071900SDave Airlie args.v3.acConfig.ucDigSel = enc_override; 938bf071900SDave Airlie else 93958cdcb8bSAlex Deucher args.v3.acConfig.ucDigSel = dig->dig_encoder; 9401f0e2943SAlex Deucher args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder); 94158cdcb8bSAlex Deucher break; 94258cdcb8bSAlex Deucher case 4: 94358cdcb8bSAlex Deucher args.v4.ucAction = action; 94458cdcb8bSAlex Deucher args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 94558cdcb8bSAlex Deucher if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 94658cdcb8bSAlex Deucher args.v4.ucPanelMode = panel_mode; 94758cdcb8bSAlex Deucher else 94858cdcb8bSAlex Deucher args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder); 94958cdcb8bSAlex Deucher 9502f6fa79aSAlex Deucher if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) 95158cdcb8bSAlex Deucher args.v4.ucLaneNum = dp_lane_count; 9529aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 95358cdcb8bSAlex Deucher args.v4.ucLaneNum = 8; 95458cdcb8bSAlex Deucher else 95558cdcb8bSAlex Deucher args.v4.ucLaneNum = 4; 95658cdcb8bSAlex Deucher 9572f6fa79aSAlex Deucher if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)) { 958e68adef8SAlex Deucher if (dp_clock == 540000) 9593f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; 960e68adef8SAlex Deucher else if (dp_clock == 324000) 961e68adef8SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ; 962e68adef8SAlex Deucher else if (dp_clock == 270000) 963e68adef8SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; 964e68adef8SAlex Deucher else 965e68adef8SAlex Deucher args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ; 9663f03ced8SAlex Deucher } 967bf071900SDave Airlie 968bf071900SDave Airlie if (enc_override != -1) 969bf071900SDave Airlie args.v4.acConfig.ucDigSel = enc_override; 970bf071900SDave Airlie else 9713f03ced8SAlex Deucher args.v4.acConfig.ucDigSel = dig->dig_encoder; 9721f0e2943SAlex Deucher args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder); 9733f03ced8SAlex Deucher if (hpd_id == RADEON_HPD_NONE) 9743f03ced8SAlex Deucher args.v4.ucHPD_ID = 0; 9753f03ced8SAlex Deucher else 9763f03ced8SAlex Deucher args.v4.ucHPD_ID = hpd_id + 1; 9773f03ced8SAlex Deucher break; 9783f03ced8SAlex Deucher default: 97958cdcb8bSAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 9803f03ced8SAlex Deucher break; 9813f03ced8SAlex Deucher } 9823f03ced8SAlex Deucher break; 98358cdcb8bSAlex Deucher default: 98458cdcb8bSAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 9853f03ced8SAlex Deucher break; 9863f03ced8SAlex Deucher } 9873f03ced8SAlex Deucher 9883f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 9893f03ced8SAlex Deucher 9903f03ced8SAlex Deucher } 9913f03ced8SAlex Deucher 992bf071900SDave Airlie void 993bf071900SDave Airlie atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode) 994bf071900SDave Airlie { 995bf071900SDave Airlie atombios_dig_encoder_setup2(encoder, action, panel_mode, -1); 996bf071900SDave Airlie } 997bf071900SDave Airlie 9983f03ced8SAlex Deucher union dig_transmitter_control { 9993f03ced8SAlex Deucher DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 10003f03ced8SAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 10013f03ced8SAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 10023f03ced8SAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; 100347aef7a8SAlex Deucher DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5; 10043f03ced8SAlex Deucher }; 10053f03ced8SAlex Deucher 10063f03ced8SAlex Deucher void 1007bf071900SDave Airlie atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe) 10083f03ced8SAlex Deucher { 10093f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 10103f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 10113f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 10123f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 10133f03ced8SAlex Deucher struct drm_connector *connector; 10143f03ced8SAlex Deucher union dig_transmitter_control args; 10153f03ced8SAlex Deucher int index = 0; 10163f03ced8SAlex Deucher uint8_t frev, crev; 10173f03ced8SAlex Deucher bool is_dp = false; 10183f03ced8SAlex Deucher int pll_id = 0; 10193f03ced8SAlex Deucher int dp_clock = 0; 10203f03ced8SAlex Deucher int dp_lane_count = 0; 10213f03ced8SAlex Deucher int connector_object_id = 0; 10223f03ced8SAlex Deucher int igp_lane_info = 0; 10233f03ced8SAlex Deucher int dig_encoder = dig->dig_encoder; 102447aef7a8SAlex Deucher int hpd_id = RADEON_HPD_NONE; 10253f03ced8SAlex Deucher 10263f03ced8SAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 10273f03ced8SAlex Deucher connector = radeon_get_connector_for_encoder_init(encoder); 10283f03ced8SAlex Deucher /* just needed to avoid bailing in the encoder check. the encoder 10293f03ced8SAlex Deucher * isn't used for init 10303f03ced8SAlex Deucher */ 10313f03ced8SAlex Deucher dig_encoder = 0; 10323f03ced8SAlex Deucher } else 10333f03ced8SAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 10343f03ced8SAlex Deucher 10353f03ced8SAlex Deucher if (connector) { 10363f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 10373f03ced8SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 10383f03ced8SAlex Deucher radeon_connector->con_priv; 10393f03ced8SAlex Deucher 104047aef7a8SAlex Deucher hpd_id = radeon_connector->hpd.hpd; 10413f03ced8SAlex Deucher dp_clock = dig_connector->dp_clock; 10423f03ced8SAlex Deucher dp_lane_count = dig_connector->dp_lane_count; 10433f03ced8SAlex Deucher connector_object_id = 10443f03ced8SAlex Deucher (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 10453f03ced8SAlex Deucher igp_lane_info = dig_connector->igp_lane_info; 10463f03ced8SAlex Deucher } 10473f03ced8SAlex Deucher 1048a3b08294SAlex Deucher if (encoder->crtc) { 1049a3b08294SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1050a3b08294SAlex Deucher pll_id = radeon_crtc->pll_id; 1051a3b08294SAlex Deucher } 1052a3b08294SAlex Deucher 10533f03ced8SAlex Deucher /* no dig encoder assigned */ 10543f03ced8SAlex Deucher if (dig_encoder == -1) 10553f03ced8SAlex Deucher return; 10563f03ced8SAlex Deucher 10573f03ced8SAlex Deucher if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))) 10583f03ced8SAlex Deucher is_dp = true; 10593f03ced8SAlex Deucher 10603f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 10613f03ced8SAlex Deucher 10623f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 10633f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 10643f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 10653f03ced8SAlex Deucher break; 10663f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 10673f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 10683f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1069e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 10703f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 10713f03ced8SAlex Deucher break; 10723f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 10733f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); 10743f03ced8SAlex Deucher break; 10753f03ced8SAlex Deucher } 10763f03ced8SAlex Deucher 10773f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 10783f03ced8SAlex Deucher return; 10793f03ced8SAlex Deucher 1080a3b08294SAlex Deucher switch (frev) { 1081a3b08294SAlex Deucher case 1: 1082a3b08294SAlex Deucher switch (crev) { 1083a3b08294SAlex Deucher case 1: 10843f03ced8SAlex Deucher args.v1.ucAction = action; 10853f03ced8SAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 10863f03ced8SAlex Deucher args.v1.usInitInfo = cpu_to_le16(connector_object_id); 10873f03ced8SAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 10883f03ced8SAlex Deucher args.v1.asMode.ucLaneSel = lane_num; 10893f03ced8SAlex Deucher args.v1.asMode.ucLaneSet = lane_set; 10903f03ced8SAlex Deucher } else { 10913f03ced8SAlex Deucher if (is_dp) 10926e76a2dfSAlex Deucher args.v1.usPixelClock = cpu_to_le16(dp_clock / 10); 10939aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 10943f03ced8SAlex Deucher args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 10953f03ced8SAlex Deucher else 10963f03ced8SAlex Deucher args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 10973f03ced8SAlex Deucher } 10983f03ced8SAlex Deucher 10993f03ced8SAlex Deucher args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 11003f03ced8SAlex Deucher 11013f03ced8SAlex Deucher if (dig_encoder) 11023f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 11033f03ced8SAlex Deucher else 11043f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 11053f03ced8SAlex Deucher 11063f03ced8SAlex Deucher if ((rdev->flags & RADEON_IS_IGP) && 11073f03ced8SAlex Deucher (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 11089aa59993SAlex Deucher if (is_dp || 11099aa59993SAlex Deucher !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) { 11103f03ced8SAlex Deucher if (igp_lane_info & 0x1) 11113f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 11123f03ced8SAlex Deucher else if (igp_lane_info & 0x2) 11133f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 11143f03ced8SAlex Deucher else if (igp_lane_info & 0x4) 11153f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 11163f03ced8SAlex Deucher else if (igp_lane_info & 0x8) 11173f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 11183f03ced8SAlex Deucher } else { 11193f03ced8SAlex Deucher if (igp_lane_info & 0x3) 11203f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 11213f03ced8SAlex Deucher else if (igp_lane_info & 0xc) 11223f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 11233f03ced8SAlex Deucher } 11243f03ced8SAlex Deucher } 11253f03ced8SAlex Deucher 11263f03ced8SAlex Deucher if (dig->linkb) 11273f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 11283f03ced8SAlex Deucher else 11293f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 11303f03ced8SAlex Deucher 11313f03ced8SAlex Deucher if (is_dp) 11323f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 11333f03ced8SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 11343f03ced8SAlex Deucher if (dig->coherent_mode) 11353f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 11369aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 11373f03ced8SAlex Deucher args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 11383f03ced8SAlex Deucher } 1139a3b08294SAlex Deucher break; 1140a3b08294SAlex Deucher case 2: 1141a3b08294SAlex Deucher args.v2.ucAction = action; 1142a3b08294SAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1143a3b08294SAlex Deucher args.v2.usInitInfo = cpu_to_le16(connector_object_id); 1144a3b08294SAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1145a3b08294SAlex Deucher args.v2.asMode.ucLaneSel = lane_num; 1146a3b08294SAlex Deucher args.v2.asMode.ucLaneSet = lane_set; 1147a3b08294SAlex Deucher } else { 1148a3b08294SAlex Deucher if (is_dp) 11496e76a2dfSAlex Deucher args.v2.usPixelClock = cpu_to_le16(dp_clock / 10); 11509aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1151a3b08294SAlex Deucher args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1152a3b08294SAlex Deucher else 1153a3b08294SAlex Deucher args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1154a3b08294SAlex Deucher } 1155a3b08294SAlex Deucher 1156a3b08294SAlex Deucher args.v2.acConfig.ucEncoderSel = dig_encoder; 1157a3b08294SAlex Deucher if (dig->linkb) 1158a3b08294SAlex Deucher args.v2.acConfig.ucLinkSel = 1; 1159a3b08294SAlex Deucher 1160a3b08294SAlex Deucher switch (radeon_encoder->encoder_id) { 1161a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1162a3b08294SAlex Deucher args.v2.acConfig.ucTransmitterSel = 0; 1163a3b08294SAlex Deucher break; 1164a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1165a3b08294SAlex Deucher args.v2.acConfig.ucTransmitterSel = 1; 1166a3b08294SAlex Deucher break; 1167a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1168a3b08294SAlex Deucher args.v2.acConfig.ucTransmitterSel = 2; 1169a3b08294SAlex Deucher break; 1170a3b08294SAlex Deucher } 1171a3b08294SAlex Deucher 1172a3b08294SAlex Deucher if (is_dp) { 1173a3b08294SAlex Deucher args.v2.acConfig.fCoherentMode = 1; 1174a3b08294SAlex Deucher args.v2.acConfig.fDPConnector = 1; 1175a3b08294SAlex Deucher } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1176a3b08294SAlex Deucher if (dig->coherent_mode) 1177a3b08294SAlex Deucher args.v2.acConfig.fCoherentMode = 1; 11789aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1179a3b08294SAlex Deucher args.v2.acConfig.fDualLinkConnector = 1; 1180a3b08294SAlex Deucher } 1181a3b08294SAlex Deucher break; 1182a3b08294SAlex Deucher case 3: 1183a3b08294SAlex Deucher args.v3.ucAction = action; 1184a3b08294SAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1185a3b08294SAlex Deucher args.v3.usInitInfo = cpu_to_le16(connector_object_id); 1186a3b08294SAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1187a3b08294SAlex Deucher args.v3.asMode.ucLaneSel = lane_num; 1188a3b08294SAlex Deucher args.v3.asMode.ucLaneSet = lane_set; 1189a3b08294SAlex Deucher } else { 1190a3b08294SAlex Deucher if (is_dp) 11916e76a2dfSAlex Deucher args.v3.usPixelClock = cpu_to_le16(dp_clock / 10); 11929aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1193a3b08294SAlex Deucher args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1194a3b08294SAlex Deucher else 1195a3b08294SAlex Deucher args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1196a3b08294SAlex Deucher } 1197a3b08294SAlex Deucher 1198a3b08294SAlex Deucher if (is_dp) 1199a3b08294SAlex Deucher args.v3.ucLaneNum = dp_lane_count; 12009aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1201a3b08294SAlex Deucher args.v3.ucLaneNum = 8; 1202a3b08294SAlex Deucher else 1203a3b08294SAlex Deucher args.v3.ucLaneNum = 4; 1204a3b08294SAlex Deucher 1205a3b08294SAlex Deucher if (dig->linkb) 1206a3b08294SAlex Deucher args.v3.acConfig.ucLinkSel = 1; 1207a3b08294SAlex Deucher if (dig_encoder & 1) 1208a3b08294SAlex Deucher args.v3.acConfig.ucEncoderSel = 1; 1209a3b08294SAlex Deucher 1210a3b08294SAlex Deucher /* Select the PLL for the PHY 1211a3b08294SAlex Deucher * DP PHY should be clocked from external src if there is 1212a3b08294SAlex Deucher * one. 1213a3b08294SAlex Deucher */ 1214a3b08294SAlex Deucher /* On DCE4, if there is an external clock, it generates the DP ref clock */ 1215a3b08294SAlex Deucher if (is_dp && rdev->clock.dp_extclk) 1216a3b08294SAlex Deucher args.v3.acConfig.ucRefClkSource = 2; /* external src */ 1217a3b08294SAlex Deucher else 1218a3b08294SAlex Deucher args.v3.acConfig.ucRefClkSource = pll_id; 1219a3b08294SAlex Deucher 1220a3b08294SAlex Deucher switch (radeon_encoder->encoder_id) { 1221a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1222a3b08294SAlex Deucher args.v3.acConfig.ucTransmitterSel = 0; 1223a3b08294SAlex Deucher break; 1224a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1225a3b08294SAlex Deucher args.v3.acConfig.ucTransmitterSel = 1; 1226a3b08294SAlex Deucher break; 1227a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1228a3b08294SAlex Deucher args.v3.acConfig.ucTransmitterSel = 2; 1229a3b08294SAlex Deucher break; 1230a3b08294SAlex Deucher } 1231a3b08294SAlex Deucher 1232a3b08294SAlex Deucher if (is_dp) 1233a3b08294SAlex Deucher args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ 1234a3b08294SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1235a3b08294SAlex Deucher if (dig->coherent_mode) 1236a3b08294SAlex Deucher args.v3.acConfig.fCoherentMode = 1; 12379aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1238a3b08294SAlex Deucher args.v3.acConfig.fDualLinkConnector = 1; 1239a3b08294SAlex Deucher } 1240a3b08294SAlex Deucher break; 1241a3b08294SAlex Deucher case 4: 1242a3b08294SAlex Deucher args.v4.ucAction = action; 1243a3b08294SAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_INIT) { 1244a3b08294SAlex Deucher args.v4.usInitInfo = cpu_to_le16(connector_object_id); 1245a3b08294SAlex Deucher } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1246a3b08294SAlex Deucher args.v4.asMode.ucLaneSel = lane_num; 1247a3b08294SAlex Deucher args.v4.asMode.ucLaneSet = lane_set; 1248a3b08294SAlex Deucher } else { 1249a3b08294SAlex Deucher if (is_dp) 12506e76a2dfSAlex Deucher args.v4.usPixelClock = cpu_to_le16(dp_clock / 10); 12519aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1252a3b08294SAlex Deucher args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); 1253a3b08294SAlex Deucher else 1254a3b08294SAlex Deucher args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 1255a3b08294SAlex Deucher } 1256a3b08294SAlex Deucher 1257a3b08294SAlex Deucher if (is_dp) 1258a3b08294SAlex Deucher args.v4.ucLaneNum = dp_lane_count; 12599aa59993SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1260a3b08294SAlex Deucher args.v4.ucLaneNum = 8; 1261a3b08294SAlex Deucher else 1262a3b08294SAlex Deucher args.v4.ucLaneNum = 4; 1263a3b08294SAlex Deucher 1264a3b08294SAlex Deucher if (dig->linkb) 1265a3b08294SAlex Deucher args.v4.acConfig.ucLinkSel = 1; 1266a3b08294SAlex Deucher if (dig_encoder & 1) 1267a3b08294SAlex Deucher args.v4.acConfig.ucEncoderSel = 1; 1268a3b08294SAlex Deucher 1269a3b08294SAlex Deucher /* Select the PLL for the PHY 1270a3b08294SAlex Deucher * DP PHY should be clocked from external src if there is 1271a3b08294SAlex Deucher * one. 1272a3b08294SAlex Deucher */ 1273a3b08294SAlex Deucher /* On DCE5 DCPLL usually generates the DP ref clock */ 1274a3b08294SAlex Deucher if (is_dp) { 1275a3b08294SAlex Deucher if (rdev->clock.dp_extclk) 1276a3b08294SAlex Deucher args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK; 1277a3b08294SAlex Deucher else 1278a3b08294SAlex Deucher args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL; 1279a3b08294SAlex Deucher } else 1280a3b08294SAlex Deucher args.v4.acConfig.ucRefClkSource = pll_id; 1281a3b08294SAlex Deucher 1282a3b08294SAlex Deucher switch (radeon_encoder->encoder_id) { 1283a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1284a3b08294SAlex Deucher args.v4.acConfig.ucTransmitterSel = 0; 1285a3b08294SAlex Deucher break; 1286a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1287a3b08294SAlex Deucher args.v4.acConfig.ucTransmitterSel = 1; 1288a3b08294SAlex Deucher break; 1289a3b08294SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1290a3b08294SAlex Deucher args.v4.acConfig.ucTransmitterSel = 2; 1291a3b08294SAlex Deucher break; 1292a3b08294SAlex Deucher } 1293a3b08294SAlex Deucher 1294a3b08294SAlex Deucher if (is_dp) 1295a3b08294SAlex Deucher args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */ 1296a3b08294SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 1297a3b08294SAlex Deucher if (dig->coherent_mode) 1298a3b08294SAlex Deucher args.v4.acConfig.fCoherentMode = 1; 12999aa59993SAlex Deucher if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 1300a3b08294SAlex Deucher args.v4.acConfig.fDualLinkConnector = 1; 1301a3b08294SAlex Deucher } 1302a3b08294SAlex Deucher break; 130347aef7a8SAlex Deucher case 5: 130447aef7a8SAlex Deucher args.v5.ucAction = action; 130547aef7a8SAlex Deucher if (is_dp) 130647aef7a8SAlex Deucher args.v5.usSymClock = cpu_to_le16(dp_clock / 10); 130747aef7a8SAlex Deucher else 130847aef7a8SAlex Deucher args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 130947aef7a8SAlex Deucher 131047aef7a8SAlex Deucher switch (radeon_encoder->encoder_id) { 131147aef7a8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 131247aef7a8SAlex Deucher if (dig->linkb) 131347aef7a8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB; 131447aef7a8SAlex Deucher else 131547aef7a8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA; 131647aef7a8SAlex Deucher break; 131747aef7a8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 131847aef7a8SAlex Deucher if (dig->linkb) 131947aef7a8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD; 132047aef7a8SAlex Deucher else 132147aef7a8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC; 132247aef7a8SAlex Deucher break; 132347aef7a8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 132447aef7a8SAlex Deucher if (dig->linkb) 132547aef7a8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF; 132647aef7a8SAlex Deucher else 132747aef7a8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE; 132847aef7a8SAlex Deucher break; 1329e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 1330e68adef8SAlex Deucher args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG; 1331e68adef8SAlex Deucher break; 133247aef7a8SAlex Deucher } 133347aef7a8SAlex Deucher if (is_dp) 133447aef7a8SAlex Deucher args.v5.ucLaneNum = dp_lane_count; 1335d03874c8SAlex Deucher else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 133647aef7a8SAlex Deucher args.v5.ucLaneNum = 8; 133747aef7a8SAlex Deucher else 133847aef7a8SAlex Deucher args.v5.ucLaneNum = 4; 133947aef7a8SAlex Deucher args.v5.ucConnObjId = connector_object_id; 134047aef7a8SAlex Deucher args.v5.ucDigMode = atombios_get_encoder_mode(encoder); 134147aef7a8SAlex Deucher 134247aef7a8SAlex Deucher if (is_dp && rdev->clock.dp_extclk) 134347aef7a8SAlex Deucher args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK; 134447aef7a8SAlex Deucher else 134547aef7a8SAlex Deucher args.v5.asConfig.ucPhyClkSrcId = pll_id; 134647aef7a8SAlex Deucher 134747aef7a8SAlex Deucher if (is_dp) 134847aef7a8SAlex Deucher args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */ 134947aef7a8SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 135047aef7a8SAlex Deucher if (dig->coherent_mode) 135147aef7a8SAlex Deucher args.v5.asConfig.ucCoherentMode = 1; 135247aef7a8SAlex Deucher } 135347aef7a8SAlex Deucher if (hpd_id == RADEON_HPD_NONE) 135447aef7a8SAlex Deucher args.v5.asConfig.ucHPDSel = 0; 135547aef7a8SAlex Deucher else 135647aef7a8SAlex Deucher args.v5.asConfig.ucHPDSel = hpd_id + 1; 1357bf071900SDave Airlie args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder); 135847aef7a8SAlex Deucher args.v5.ucDPLaneSet = lane_set; 135947aef7a8SAlex Deucher break; 1360a3b08294SAlex Deucher default: 1361a3b08294SAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 1362a3b08294SAlex Deucher break; 1363a3b08294SAlex Deucher } 1364a3b08294SAlex Deucher break; 1365a3b08294SAlex Deucher default: 1366a3b08294SAlex Deucher DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 1367a3b08294SAlex Deucher break; 13683f03ced8SAlex Deucher } 13693f03ced8SAlex Deucher 13703f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 13713f03ced8SAlex Deucher } 13723f03ced8SAlex Deucher 1373bf071900SDave Airlie void 1374bf071900SDave Airlie atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) 1375bf071900SDave Airlie { 1376bf071900SDave Airlie atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1); 1377bf071900SDave Airlie } 1378bf071900SDave Airlie 13793f03ced8SAlex Deucher bool 13803f03ced8SAlex Deucher atombios_set_edp_panel_power(struct drm_connector *connector, int action) 13813f03ced8SAlex Deucher { 13823f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 13833f03ced8SAlex Deucher struct drm_device *dev = radeon_connector->base.dev; 13843f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 13853f03ced8SAlex Deucher union dig_transmitter_control args; 13863f03ced8SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 13873f03ced8SAlex Deucher uint8_t frev, crev; 13883f03ced8SAlex Deucher 13893f03ced8SAlex Deucher if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) 13903f03ced8SAlex Deucher goto done; 13913f03ced8SAlex Deucher 13923f03ced8SAlex Deucher if (!ASIC_IS_DCE4(rdev)) 13933f03ced8SAlex Deucher goto done; 13943f03ced8SAlex Deucher 13953f03ced8SAlex Deucher if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) && 13963f03ced8SAlex Deucher (action != ATOM_TRANSMITTER_ACTION_POWER_OFF)) 13973f03ced8SAlex Deucher goto done; 13983f03ced8SAlex Deucher 13993f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 14003f03ced8SAlex Deucher goto done; 14013f03ced8SAlex Deucher 14023f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 14033f03ced8SAlex Deucher 14043f03ced8SAlex Deucher args.v1.ucAction = action; 14053f03ced8SAlex Deucher 14063f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 14073f03ced8SAlex Deucher 14083f03ced8SAlex Deucher /* wait for the panel to power up */ 14093f03ced8SAlex Deucher if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) { 14103f03ced8SAlex Deucher int i; 14113f03ced8SAlex Deucher 14123f03ced8SAlex Deucher for (i = 0; i < 300; i++) { 14133f03ced8SAlex Deucher if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) 14143f03ced8SAlex Deucher return true; 14153f03ced8SAlex Deucher mdelay(1); 14163f03ced8SAlex Deucher } 14173f03ced8SAlex Deucher return false; 14183f03ced8SAlex Deucher } 14193f03ced8SAlex Deucher done: 14203f03ced8SAlex Deucher return true; 14213f03ced8SAlex Deucher } 14223f03ced8SAlex Deucher 14233f03ced8SAlex Deucher union external_encoder_control { 14243f03ced8SAlex Deucher EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 14253f03ced8SAlex Deucher EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 14263f03ced8SAlex Deucher }; 14273f03ced8SAlex Deucher 14283f03ced8SAlex Deucher static void 14293f03ced8SAlex Deucher atombios_external_encoder_setup(struct drm_encoder *encoder, 14303f03ced8SAlex Deucher struct drm_encoder *ext_encoder, 14313f03ced8SAlex Deucher int action) 14323f03ced8SAlex Deucher { 14333f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 14343f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 14353f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 14363f03ced8SAlex Deucher struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); 14373f03ced8SAlex Deucher union external_encoder_control args; 14383f03ced8SAlex Deucher struct drm_connector *connector; 14393f03ced8SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 14403f03ced8SAlex Deucher u8 frev, crev; 14413f03ced8SAlex Deucher int dp_clock = 0; 14423f03ced8SAlex Deucher int dp_lane_count = 0; 14433f03ced8SAlex Deucher int connector_object_id = 0; 14443f03ced8SAlex Deucher u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 14453f03ced8SAlex Deucher 14463f03ced8SAlex Deucher if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) 14473f03ced8SAlex Deucher connector = radeon_get_connector_for_encoder_init(encoder); 14483f03ced8SAlex Deucher else 14493f03ced8SAlex Deucher connector = radeon_get_connector_for_encoder(encoder); 14503f03ced8SAlex Deucher 14513f03ced8SAlex Deucher if (connector) { 14523f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 14533f03ced8SAlex Deucher struct radeon_connector_atom_dig *dig_connector = 14543f03ced8SAlex Deucher radeon_connector->con_priv; 14553f03ced8SAlex Deucher 14563f03ced8SAlex Deucher dp_clock = dig_connector->dp_clock; 14573f03ced8SAlex Deucher dp_lane_count = dig_connector->dp_lane_count; 14583f03ced8SAlex Deucher connector_object_id = 14593f03ced8SAlex Deucher (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 14603f03ced8SAlex Deucher } 14613f03ced8SAlex Deucher 14623f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 14633f03ced8SAlex Deucher 14643f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 14653f03ced8SAlex Deucher return; 14663f03ced8SAlex Deucher 14673f03ced8SAlex Deucher switch (frev) { 14683f03ced8SAlex Deucher case 1: 14693f03ced8SAlex Deucher /* no params on frev 1 */ 14703f03ced8SAlex Deucher break; 14713f03ced8SAlex Deucher case 2: 14723f03ced8SAlex Deucher switch (crev) { 14733f03ced8SAlex Deucher case 1: 14743f03ced8SAlex Deucher case 2: 14753f03ced8SAlex Deucher args.v1.sDigEncoder.ucAction = action; 14763f03ced8SAlex Deucher args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 14773f03ced8SAlex Deucher args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); 14783f03ced8SAlex Deucher 14793f03ced8SAlex Deucher if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)) { 14803f03ced8SAlex Deucher if (dp_clock == 270000) 14813f03ced8SAlex Deucher args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 14823f03ced8SAlex Deucher args.v1.sDigEncoder.ucLaneNum = dp_lane_count; 14839aa59993SAlex Deucher } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 14843f03ced8SAlex Deucher args.v1.sDigEncoder.ucLaneNum = 8; 14853f03ced8SAlex Deucher else 14863f03ced8SAlex Deucher args.v1.sDigEncoder.ucLaneNum = 4; 14873f03ced8SAlex Deucher break; 14883f03ced8SAlex Deucher case 3: 14893f03ced8SAlex Deucher args.v3.sExtEncoder.ucAction = action; 14903f03ced8SAlex Deucher if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) 14913f03ced8SAlex Deucher args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id); 14923f03ced8SAlex Deucher else 14933f03ced8SAlex Deucher args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 14943f03ced8SAlex Deucher args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); 14953f03ced8SAlex Deucher 14963f03ced8SAlex Deucher if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) { 14973f03ced8SAlex Deucher if (dp_clock == 270000) 14983f03ced8SAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 14993f03ced8SAlex Deucher else if (dp_clock == 540000) 15003f03ced8SAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 15013f03ced8SAlex Deucher args.v3.sExtEncoder.ucLaneNum = dp_lane_count; 15029aa59993SAlex Deucher } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) 15033f03ced8SAlex Deucher args.v3.sExtEncoder.ucLaneNum = 8; 15043f03ced8SAlex Deucher else 15053f03ced8SAlex Deucher args.v3.sExtEncoder.ucLaneNum = 4; 15063f03ced8SAlex Deucher switch (ext_enum) { 15073f03ced8SAlex Deucher case GRAPH_OBJECT_ENUM_ID1: 15083f03ced8SAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 15093f03ced8SAlex Deucher break; 15103f03ced8SAlex Deucher case GRAPH_OBJECT_ENUM_ID2: 15113f03ced8SAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 15123f03ced8SAlex Deucher break; 15133f03ced8SAlex Deucher case GRAPH_OBJECT_ENUM_ID3: 15143f03ced8SAlex Deucher args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 15153f03ced8SAlex Deucher break; 15163f03ced8SAlex Deucher } 15171f0e2943SAlex Deucher args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder); 15183f03ced8SAlex Deucher break; 15193f03ced8SAlex Deucher default: 15203f03ced8SAlex Deucher DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 15213f03ced8SAlex Deucher return; 15223f03ced8SAlex Deucher } 15233f03ced8SAlex Deucher break; 15243f03ced8SAlex Deucher default: 15253f03ced8SAlex Deucher DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 15263f03ced8SAlex Deucher return; 15273f03ced8SAlex Deucher } 15283f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 15293f03ced8SAlex Deucher } 15303f03ced8SAlex Deucher 15313f03ced8SAlex Deucher static void 15323f03ced8SAlex Deucher atombios_yuv_setup(struct drm_encoder *encoder, bool enable) 15333f03ced8SAlex Deucher { 15343f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 15353f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 15363f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 15373f03ced8SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 15383f03ced8SAlex Deucher ENABLE_YUV_PS_ALLOCATION args; 15393f03ced8SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); 15403f03ced8SAlex Deucher uint32_t temp, reg; 15413f03ced8SAlex Deucher 15423f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 15433f03ced8SAlex Deucher 15443f03ced8SAlex Deucher if (rdev->family >= CHIP_R600) 15453f03ced8SAlex Deucher reg = R600_BIOS_3_SCRATCH; 15463f03ced8SAlex Deucher else 15473f03ced8SAlex Deucher reg = RADEON_BIOS_3_SCRATCH; 15483f03ced8SAlex Deucher 15493f03ced8SAlex Deucher /* XXX: fix up scratch reg handling */ 15503f03ced8SAlex Deucher temp = RREG32(reg); 15513f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 15523f03ced8SAlex Deucher WREG32(reg, (ATOM_S3_TV1_ACTIVE | 15533f03ced8SAlex Deucher (radeon_crtc->crtc_id << 18))); 15543f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 15553f03ced8SAlex Deucher WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); 15563f03ced8SAlex Deucher else 15573f03ced8SAlex Deucher WREG32(reg, 0); 15583f03ced8SAlex Deucher 15593f03ced8SAlex Deucher if (enable) 15603f03ced8SAlex Deucher args.ucEnable = ATOM_ENABLE; 15613f03ced8SAlex Deucher args.ucCRTC = radeon_crtc->crtc_id; 15623f03ced8SAlex Deucher 15633f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 15643f03ced8SAlex Deucher 15653f03ced8SAlex Deucher WREG32(reg, temp); 15663f03ced8SAlex Deucher } 15673f03ced8SAlex Deucher 15683f03ced8SAlex Deucher static void 15693f03ced8SAlex Deucher radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode) 15703f03ced8SAlex Deucher { 15713f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 15723f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 15733f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 15743f03ced8SAlex Deucher DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 15753f03ced8SAlex Deucher int index = 0; 15763f03ced8SAlex Deucher 15773f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 15783f03ced8SAlex Deucher 15793f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 15803f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 15813f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 15823f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 15833f03ced8SAlex Deucher break; 15843f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 15853f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 15863f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 15873f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 15883f03ced8SAlex Deucher break; 15893f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 15903f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 15913f03ced8SAlex Deucher break; 15923f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 15933f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 15943f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 15953f03ced8SAlex Deucher else 15963f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 15973f03ced8SAlex Deucher break; 15983f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 15993f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 16003f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 16013f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 16023f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 16033f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 16043f03ced8SAlex Deucher else 16053f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 16063f03ced8SAlex Deucher break; 16073f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 16083f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 16093f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 16103f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 16113f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 16123f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 16133f03ced8SAlex Deucher else 16143f03ced8SAlex Deucher index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 16153f03ced8SAlex Deucher break; 16163f03ced8SAlex Deucher default: 16173f03ced8SAlex Deucher return; 16183f03ced8SAlex Deucher } 16193f03ced8SAlex Deucher 16203f03ced8SAlex Deucher switch (mode) { 16213f03ced8SAlex Deucher case DRM_MODE_DPMS_ON: 16223f03ced8SAlex Deucher args.ucAction = ATOM_ENABLE; 16233f03ced8SAlex Deucher /* workaround for DVOOutputControl on some RS690 systems */ 16243f03ced8SAlex Deucher if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) { 16253f03ced8SAlex Deucher u32 reg = RREG32(RADEON_BIOS_3_SCRATCH); 16263f03ced8SAlex Deucher WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE); 16273f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 16283f03ced8SAlex Deucher WREG32(RADEON_BIOS_3_SCRATCH, reg); 16293f03ced8SAlex Deucher } else 16303f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 16313f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1632ae93580eSAlex Deucher if (rdev->mode_info.bl_encoder) { 16334281f46eSMichel Dänzer struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 16344281f46eSMichel Dänzer 16354281f46eSMichel Dänzer atombios_set_backlight_level(radeon_encoder, dig->backlight_level); 1636ae93580eSAlex Deucher } else { 1637ae93580eSAlex Deucher args.ucAction = ATOM_LCD_BLON; 1638ae93580eSAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 1639ae93580eSAlex Deucher } 16403f03ced8SAlex Deucher } 16413f03ced8SAlex Deucher break; 16423f03ced8SAlex Deucher case DRM_MODE_DPMS_STANDBY: 16433f03ced8SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 16443f03ced8SAlex Deucher case DRM_MODE_DPMS_OFF: 16453f03ced8SAlex Deucher args.ucAction = ATOM_DISABLE; 16463f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 16473f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 16483f03ced8SAlex Deucher args.ucAction = ATOM_LCD_BLOFF; 16493f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 16503f03ced8SAlex Deucher } 16513f03ced8SAlex Deucher break; 16523f03ced8SAlex Deucher } 16533f03ced8SAlex Deucher } 16543f03ced8SAlex Deucher 16553f03ced8SAlex Deucher static void 16563f03ced8SAlex Deucher radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) 16573f03ced8SAlex Deucher { 16583f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 16593f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 16603f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 16618d1af57aSAlex Deucher struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 16628d1af57aSAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 16633f03ced8SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 16643f03ced8SAlex Deucher struct radeon_connector *radeon_connector = NULL; 16653f03ced8SAlex Deucher struct radeon_connector_atom_dig *radeon_dig_connector = NULL; 16666f50e075SAlex Deucher bool travis_quirk = false; 16673f03ced8SAlex Deucher 16683f03ced8SAlex Deucher if (connector) { 16693f03ced8SAlex Deucher radeon_connector = to_radeon_connector(connector); 16703f03ced8SAlex Deucher radeon_dig_connector = radeon_connector->con_priv; 16716f50e075SAlex Deucher if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == 16726f50e075SAlex Deucher ENCODER_OBJECT_ID_TRAVIS) && 16736f50e075SAlex Deucher (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 16746f50e075SAlex Deucher !ASIC_IS_DCE5(rdev)) 16756f50e075SAlex Deucher travis_quirk = true; 16763f03ced8SAlex Deucher } 16773f03ced8SAlex Deucher 16783f03ced8SAlex Deucher switch (mode) { 16793f03ced8SAlex Deucher case DRM_MODE_DPMS_ON: 16808d1af57aSAlex Deucher if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { 16818d1af57aSAlex Deucher if (!connector) 16828d1af57aSAlex Deucher dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 16838d1af57aSAlex Deucher else 16848d1af57aSAlex Deucher dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); 16858d1af57aSAlex Deucher 16868d1af57aSAlex Deucher /* setup and enable the encoder */ 1687fcedac67SJerome Glisse atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); 16888d1af57aSAlex Deucher atombios_dig_encoder_setup(encoder, 16898d1af57aSAlex Deucher ATOM_ENCODER_CMD_SETUP_PANEL_MODE, 16908d1af57aSAlex Deucher dig->panel_mode); 16918d1af57aSAlex Deucher if (ext_encoder) { 16928d1af57aSAlex Deucher if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) 16938d1af57aSAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 16948d1af57aSAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 1695fcedac67SJerome Glisse } 16968d1af57aSAlex Deucher } else if (ASIC_IS_DCE4(rdev)) { 16978d1af57aSAlex Deucher /* setup and enable the encoder */ 16988d1af57aSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); 1699fcedac67SJerome Glisse } else { 17008d1af57aSAlex Deucher /* setup and enable the encoder and transmitter */ 17018d1af57aSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); 17028d1af57aSAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 1703fcedac67SJerome Glisse } 17043f03ced8SAlex Deucher if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 17053f03ced8SAlex Deucher if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 17063f03ced8SAlex Deucher atombios_set_edp_panel_power(connector, 17073f03ced8SAlex Deucher ATOM_TRANSMITTER_ACTION_POWER_ON); 17083f03ced8SAlex Deucher radeon_dig_connector->edp_on = true; 17093f03ced8SAlex Deucher } 17106f50e075SAlex Deucher } 17116f50e075SAlex Deucher /* enable the transmitter */ 17126f50e075SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 17136f50e075SAlex Deucher if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 17146f50e075SAlex Deucher /* DP_SET_POWER_D0 is set in radeon_dp_link_train */ 17153f03ced8SAlex Deucher radeon_dp_link_train(encoder, connector); 17163f03ced8SAlex Deucher if (ASIC_IS_DCE4(rdev)) 17173f03ced8SAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); 17183f03ced8SAlex Deucher } 1719ae93580eSAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 1720ae93580eSAlex Deucher if (rdev->mode_info.bl_encoder) 17214281f46eSMichel Dänzer atombios_set_backlight_level(radeon_encoder, dig->backlight_level); 1722ae93580eSAlex Deucher else 1723ae93580eSAlex Deucher atombios_dig_transmitter_setup(encoder, 1724ae93580eSAlex Deucher ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0); 1725ae93580eSAlex Deucher } 17266f50e075SAlex Deucher if (ext_encoder) 17276f50e075SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); 17283f03ced8SAlex Deucher break; 17293f03ced8SAlex Deucher case DRM_MODE_DPMS_STANDBY: 17303f03ced8SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 17313f03ced8SAlex Deucher case DRM_MODE_DPMS_OFF: 17329843ead0SDave Airlie 17339843ead0SDave Airlie /* don't power off encoders with active MST links */ 17349843ead0SDave Airlie if (dig->active_mst_links) 17359843ead0SDave Airlie return; 17369843ead0SDave Airlie 173740390961SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 17386f50e075SAlex Deucher if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) 17396f50e075SAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); 17406f50e075SAlex Deucher } 17416f50e075SAlex Deucher if (ext_encoder) 17426f50e075SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE); 17436f50e075SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 17446f50e075SAlex Deucher atombios_dig_transmitter_setup(encoder, 17456f50e075SAlex Deucher ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0); 17466f50e075SAlex Deucher 17476f50e075SAlex Deucher if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && 17486f50e075SAlex Deucher connector && !travis_quirk) 17496f50e075SAlex Deucher radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3); 17506f50e075SAlex Deucher if (ASIC_IS_DCE4(rdev)) { 17518d1af57aSAlex Deucher /* disable the transmitter */ 17526f50e075SAlex Deucher atombios_dig_transmitter_setup(encoder, 17536f50e075SAlex Deucher ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 17548d1af57aSAlex Deucher } else { 17558d1af57aSAlex Deucher /* disable the encoder and transmitter */ 17566f50e075SAlex Deucher atombios_dig_transmitter_setup(encoder, 17576f50e075SAlex Deucher ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 17588d1af57aSAlex Deucher atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); 17598d1af57aSAlex Deucher } 17603f03ced8SAlex Deucher if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { 17616f50e075SAlex Deucher if (travis_quirk) 17626f50e075SAlex Deucher radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3); 17633f03ced8SAlex Deucher if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 17643f03ced8SAlex Deucher atombios_set_edp_panel_power(connector, 17653f03ced8SAlex Deucher ATOM_TRANSMITTER_ACTION_POWER_OFF); 17663f03ced8SAlex Deucher radeon_dig_connector->edp_on = false; 17673f03ced8SAlex Deucher } 17683f03ced8SAlex Deucher } 17693f03ced8SAlex Deucher break; 17703f03ced8SAlex Deucher } 17713f03ced8SAlex Deucher } 17723f03ced8SAlex Deucher 17733f03ced8SAlex Deucher static void 17743f03ced8SAlex Deucher radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) 17753f03ced8SAlex Deucher { 17763f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 17773f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 17783f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 17795c046a57SAlex Deucher int encoder_mode = atombios_get_encoder_mode(encoder); 17803f03ced8SAlex Deucher 17813f03ced8SAlex Deucher DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", 17823f03ced8SAlex Deucher radeon_encoder->encoder_id, mode, radeon_encoder->devices, 17833f03ced8SAlex Deucher radeon_encoder->active_device); 17845c046a57SAlex Deucher 178538aef154SAlex Deucher if ((radeon_audio != 0) && 17865c046a57SAlex Deucher ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || 178738aef154SAlex Deucher ENCODER_MODE_IS_DP(encoder_mode))) 17885c046a57SAlex Deucher radeon_audio_dpms(encoder, mode); 17895c046a57SAlex Deucher 17903f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 17913f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 17923f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 17933f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 17943f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 17953f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 17963f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 17973f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 17983f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 17993f03ced8SAlex Deucher radeon_atom_encoder_dpms_avivo(encoder, mode); 18003f03ced8SAlex Deucher break; 18013f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 18023f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 18033f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1804e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 18053f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 18063f03ced8SAlex Deucher radeon_atom_encoder_dpms_dig(encoder, mode); 18073f03ced8SAlex Deucher break; 18083f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 18093f03ced8SAlex Deucher if (ASIC_IS_DCE5(rdev)) { 18103f03ced8SAlex Deucher switch (mode) { 18113f03ced8SAlex Deucher case DRM_MODE_DPMS_ON: 18123f03ced8SAlex Deucher atombios_dvo_setup(encoder, ATOM_ENABLE); 18133f03ced8SAlex Deucher break; 18143f03ced8SAlex Deucher case DRM_MODE_DPMS_STANDBY: 18153f03ced8SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 18163f03ced8SAlex Deucher case DRM_MODE_DPMS_OFF: 18173f03ced8SAlex Deucher atombios_dvo_setup(encoder, ATOM_DISABLE); 18183f03ced8SAlex Deucher break; 18193f03ced8SAlex Deucher } 18203f03ced8SAlex Deucher } else if (ASIC_IS_DCE3(rdev)) 18213f03ced8SAlex Deucher radeon_atom_encoder_dpms_dig(encoder, mode); 18223f03ced8SAlex Deucher else 18233f03ced8SAlex Deucher radeon_atom_encoder_dpms_avivo(encoder, mode); 18243f03ced8SAlex Deucher break; 18253f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 18263f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 18273f03ced8SAlex Deucher if (ASIC_IS_DCE5(rdev)) { 18283f03ced8SAlex Deucher switch (mode) { 18293f03ced8SAlex Deucher case DRM_MODE_DPMS_ON: 18303f03ced8SAlex Deucher atombios_dac_setup(encoder, ATOM_ENABLE); 18313f03ced8SAlex Deucher break; 18323f03ced8SAlex Deucher case DRM_MODE_DPMS_STANDBY: 18333f03ced8SAlex Deucher case DRM_MODE_DPMS_SUSPEND: 18343f03ced8SAlex Deucher case DRM_MODE_DPMS_OFF: 18353f03ced8SAlex Deucher atombios_dac_setup(encoder, ATOM_DISABLE); 18363f03ced8SAlex Deucher break; 18373f03ced8SAlex Deucher } 18383f03ced8SAlex Deucher } else 18393f03ced8SAlex Deucher radeon_atom_encoder_dpms_avivo(encoder, mode); 18403f03ced8SAlex Deucher break; 18413f03ced8SAlex Deucher default: 18423f03ced8SAlex Deucher return; 18433f03ced8SAlex Deucher } 18443f03ced8SAlex Deucher 18453f03ced8SAlex Deucher radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 18463f03ced8SAlex Deucher 18473f03ced8SAlex Deucher } 18483f03ced8SAlex Deucher 18493f03ced8SAlex Deucher union crtc_source_param { 18503f03ced8SAlex Deucher SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 18513f03ced8SAlex Deucher SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 18523f03ced8SAlex Deucher }; 18533f03ced8SAlex Deucher 18543f03ced8SAlex Deucher static void 18553f03ced8SAlex Deucher atombios_set_encoder_crtc_source(struct drm_encoder *encoder) 18563f03ced8SAlex Deucher { 18573f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 18583f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 18593f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 18603f03ced8SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 18613f03ced8SAlex Deucher union crtc_source_param args; 18623f03ced8SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 18633f03ced8SAlex Deucher uint8_t frev, crev; 18643f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig; 18653f03ced8SAlex Deucher 18663f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 18673f03ced8SAlex Deucher 18683f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 18693f03ced8SAlex Deucher return; 18703f03ced8SAlex Deucher 18713f03ced8SAlex Deucher switch (frev) { 18723f03ced8SAlex Deucher case 1: 18733f03ced8SAlex Deucher switch (crev) { 18743f03ced8SAlex Deucher case 1: 18753f03ced8SAlex Deucher default: 18763f03ced8SAlex Deucher if (ASIC_IS_AVIVO(rdev)) 18773f03ced8SAlex Deucher args.v1.ucCRTC = radeon_crtc->crtc_id; 18783f03ced8SAlex Deucher else { 18793c20d544SWambui Karuga if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) 18803f03ced8SAlex Deucher args.v1.ucCRTC = radeon_crtc->crtc_id; 18813c20d544SWambui Karuga else 18823f03ced8SAlex Deucher args.v1.ucCRTC = radeon_crtc->crtc_id << 2; 18833f03ced8SAlex Deucher } 18843f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 18853f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 18863f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 18873f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 18883f03ced8SAlex Deucher break; 18893f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 18903f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 18913f03ced8SAlex Deucher if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) 18923f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 18933f03ced8SAlex Deucher else 18943f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 18953f03ced8SAlex Deucher break; 18963f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 18973f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 18983f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 18993f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 19003f03ced8SAlex Deucher break; 19013f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 19023f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 19033f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 19043f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 19053f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 19063f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 19073f03ced8SAlex Deucher else 19083f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 19093f03ced8SAlex Deucher break; 19103f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 19113f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 19123f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 19133f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 19143f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 19153f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 19163f03ced8SAlex Deucher else 19173f03ced8SAlex Deucher args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 19183f03ced8SAlex Deucher break; 19193f03ced8SAlex Deucher } 19203f03ced8SAlex Deucher break; 19213f03ced8SAlex Deucher case 2: 19223f03ced8SAlex Deucher args.v2.ucCRTC = radeon_crtc->crtc_id; 19233f03ced8SAlex Deucher if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE) { 19243f03ced8SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 19253f03ced8SAlex Deucher 19263f03ced8SAlex Deucher if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) 19273f03ced8SAlex Deucher args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; 19283f03ced8SAlex Deucher else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA) 19293f03ced8SAlex Deucher args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; 19303f03ced8SAlex Deucher else 19313f03ced8SAlex Deucher args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 193264252835SAlex Deucher } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 193364252835SAlex Deucher args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; 193464252835SAlex Deucher } else { 19353f03ced8SAlex Deucher args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); 193664252835SAlex Deucher } 19373f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 19383f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 19393f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 19403f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1941e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 19423f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 19433f03ced8SAlex Deucher dig = radeon_encoder->enc_priv; 19443f03ced8SAlex Deucher switch (dig->dig_encoder) { 19453f03ced8SAlex Deucher case 0: 19463f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 19473f03ced8SAlex Deucher break; 19483f03ced8SAlex Deucher case 1: 19493f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 19503f03ced8SAlex Deucher break; 19513f03ced8SAlex Deucher case 2: 19523f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 19533f03ced8SAlex Deucher break; 19543f03ced8SAlex Deucher case 3: 19553f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 19563f03ced8SAlex Deucher break; 19573f03ced8SAlex Deucher case 4: 19583f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 19593f03ced8SAlex Deucher break; 19603f03ced8SAlex Deucher case 5: 19613f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 19623f03ced8SAlex Deucher break; 1963e68adef8SAlex Deucher case 6: 1964e68adef8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID; 1965e68adef8SAlex Deucher break; 19663f03ced8SAlex Deucher } 19673f03ced8SAlex Deucher break; 19683f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 19693f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 19703f03ced8SAlex Deucher break; 19713f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 19723f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 19733f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 19743f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 19753f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 19763f03ced8SAlex Deucher else 19773f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 19783f03ced8SAlex Deucher break; 19793f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 19803f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 19813f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 19823f03ced8SAlex Deucher else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 19833f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 19843f03ced8SAlex Deucher else 19853f03ced8SAlex Deucher args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 19863f03ced8SAlex Deucher break; 19873f03ced8SAlex Deucher } 19883f03ced8SAlex Deucher break; 19893f03ced8SAlex Deucher } 19903f03ced8SAlex Deucher break; 19913f03ced8SAlex Deucher default: 19923f03ced8SAlex Deucher DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); 19933f03ced8SAlex Deucher return; 19943f03ced8SAlex Deucher } 19953f03ced8SAlex Deucher 19963f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 19973f03ced8SAlex Deucher 19983f03ced8SAlex Deucher /* update scratch regs with new routing */ 19993f03ced8SAlex Deucher radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 20003f03ced8SAlex Deucher } 20013f03ced8SAlex Deucher 20029843ead0SDave Airlie void 20039843ead0SDave Airlie atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe) 20049843ead0SDave Airlie { 20059843ead0SDave Airlie struct drm_device *dev = encoder->dev; 20069843ead0SDave Airlie struct radeon_device *rdev = dev->dev_private; 20079843ead0SDave Airlie struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 20089843ead0SDave Airlie int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 20099843ead0SDave Airlie uint8_t frev, crev; 20109843ead0SDave Airlie union crtc_source_param args; 20119843ead0SDave Airlie 20129843ead0SDave Airlie memset(&args, 0, sizeof(args)); 20139843ead0SDave Airlie 20149843ead0SDave Airlie if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 20159843ead0SDave Airlie return; 20169843ead0SDave Airlie 20179843ead0SDave Airlie if (frev != 1 && crev != 2) 20189843ead0SDave Airlie DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev); 20199843ead0SDave Airlie 20209843ead0SDave Airlie args.v2.ucCRTC = radeon_crtc->crtc_id; 20219843ead0SDave Airlie args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST; 20229843ead0SDave Airlie 20239843ead0SDave Airlie switch (fe) { 20249843ead0SDave Airlie case 0: 20259843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 20269843ead0SDave Airlie break; 20279843ead0SDave Airlie case 1: 20289843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 20299843ead0SDave Airlie break; 20309843ead0SDave Airlie case 2: 20319843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 20329843ead0SDave Airlie break; 20339843ead0SDave Airlie case 3: 20349843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 20359843ead0SDave Airlie break; 20369843ead0SDave Airlie case 4: 20379843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 20389843ead0SDave Airlie break; 20399843ead0SDave Airlie case 5: 20409843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 20419843ead0SDave Airlie break; 20429843ead0SDave Airlie case 6: 20439843ead0SDave Airlie args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID; 20449843ead0SDave Airlie break; 20459843ead0SDave Airlie } 20469843ead0SDave Airlie atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 20479843ead0SDave Airlie } 20489843ead0SDave Airlie 20493f03ced8SAlex Deucher static void 20503f03ced8SAlex Deucher atombios_apply_encoder_quirks(struct drm_encoder *encoder, 20513f03ced8SAlex Deucher struct drm_display_mode *mode) 20523f03ced8SAlex Deucher { 20533f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 20543f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 20553f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 20563f03ced8SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 20573f03ced8SAlex Deucher 20583f03ced8SAlex Deucher /* Funky macbooks */ 2059d86a4126SThomas Zimmermann if ((rdev->pdev->device == 0x71C5) && 2060d86a4126SThomas Zimmermann (rdev->pdev->subsystem_vendor == 0x106b) && 2061d86a4126SThomas Zimmermann (rdev->pdev->subsystem_device == 0x0080)) { 20623f03ced8SAlex Deucher if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { 20633f03ced8SAlex Deucher uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); 20643f03ced8SAlex Deucher 20653f03ced8SAlex Deucher lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; 20663f03ced8SAlex Deucher lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; 20673f03ced8SAlex Deucher 20683f03ced8SAlex Deucher WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); 20693f03ced8SAlex Deucher } 20703f03ced8SAlex Deucher } 20713f03ced8SAlex Deucher 20723f03ced8SAlex Deucher /* set scaler clears this on some chips */ 20733f03ced8SAlex Deucher if (ASIC_IS_AVIVO(rdev) && 20743f03ced8SAlex Deucher (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)))) { 2075d798f2f2SAlex Deucher if (ASIC_IS_DCE8(rdev)) { 2076d798f2f2SAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) 2077d798f2f2SAlex Deucher WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 2078d798f2f2SAlex Deucher CIK_INTERLEAVE_EN); 2079d798f2f2SAlex Deucher else 2080d798f2f2SAlex Deucher WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 2081d798f2f2SAlex Deucher } else if (ASIC_IS_DCE4(rdev)) { 20823f03ced8SAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) 20833f03ced8SAlex Deucher WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 20843f03ced8SAlex Deucher EVERGREEN_INTERLEAVE_EN); 20853f03ced8SAlex Deucher else 20863f03ced8SAlex Deucher WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 20873f03ced8SAlex Deucher } else { 20883f03ced8SAlex Deucher if (mode->flags & DRM_MODE_FLAG_INTERLACE) 20893f03ced8SAlex Deucher WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 20903f03ced8SAlex Deucher AVIVO_D1MODE_INTERLEAVE_EN); 20913f03ced8SAlex Deucher else 20923f03ced8SAlex Deucher WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); 20933f03ced8SAlex Deucher } 20943f03ced8SAlex Deucher } 20953f03ced8SAlex Deucher } 20963f03ced8SAlex Deucher 20978f0fc088SDave Airlie void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx) 20988f0fc088SDave Airlie { 20998f0fc088SDave Airlie if (enc_idx < 0) 21008f0fc088SDave Airlie return; 21018f0fc088SDave Airlie rdev->mode_info.active_encoders &= ~(1 << enc_idx); 21028f0fc088SDave Airlie } 21038f0fc088SDave Airlie 21048f0fc088SDave Airlie int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx) 21053f03ced8SAlex Deucher { 21063f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 21073f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 21083f03ced8SAlex Deucher struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 21093f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 21103f03ced8SAlex Deucher struct drm_encoder *test_encoder; 211141fa5437SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 21123f03ced8SAlex Deucher uint32_t dig_enc_in_use = 0; 21138f0fc088SDave Airlie int enc_idx = -1; 21143f03ced8SAlex Deucher 21158f0fc088SDave Airlie if (fe_idx >= 0) { 21168f0fc088SDave Airlie enc_idx = fe_idx; 21178f0fc088SDave Airlie goto assigned; 21188f0fc088SDave Airlie } 211941fa5437SAlex Deucher if (ASIC_IS_DCE6(rdev)) { 212041fa5437SAlex Deucher /* DCE6 */ 212141fa5437SAlex Deucher switch (radeon_encoder->encoder_id) { 212241fa5437SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 212341fa5437SAlex Deucher if (dig->linkb) 21248f0fc088SDave Airlie enc_idx = 1; 212541fa5437SAlex Deucher else 21268f0fc088SDave Airlie enc_idx = 0; 212741fa5437SAlex Deucher break; 212841fa5437SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 212941fa5437SAlex Deucher if (dig->linkb) 21308f0fc088SDave Airlie enc_idx = 3; 213141fa5437SAlex Deucher else 21328f0fc088SDave Airlie enc_idx = 2; 213341fa5437SAlex Deucher break; 213441fa5437SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 213541fa5437SAlex Deucher if (dig->linkb) 21368f0fc088SDave Airlie enc_idx = 5; 213741fa5437SAlex Deucher else 21388f0fc088SDave Airlie enc_idx = 4; 213941fa5437SAlex Deucher break; 2140e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 21418f0fc088SDave Airlie enc_idx = 6; 2142e68adef8SAlex Deucher break; 214341fa5437SAlex Deucher } 21448f0fc088SDave Airlie goto assigned; 214541fa5437SAlex Deucher } else if (ASIC_IS_DCE4(rdev)) { 21463f03ced8SAlex Deucher /* DCE4/5 */ 214741fa5437SAlex Deucher if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { 21483f03ced8SAlex Deucher /* ontario follows DCE4 */ 21493f03ced8SAlex Deucher if (rdev->family == CHIP_PALM) { 21503f03ced8SAlex Deucher if (dig->linkb) 21518f0fc088SDave Airlie enc_idx = 1; 21523f03ced8SAlex Deucher else 21538f0fc088SDave Airlie enc_idx = 0; 21543f03ced8SAlex Deucher } else 21553f03ced8SAlex Deucher /* llano follows DCE3.2 */ 21568f0fc088SDave Airlie enc_idx = radeon_crtc->crtc_id; 21573f03ced8SAlex Deucher } else { 21583f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 21593f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 21603f03ced8SAlex Deucher if (dig->linkb) 21618f0fc088SDave Airlie enc_idx = 1; 21623f03ced8SAlex Deucher else 21638f0fc088SDave Airlie enc_idx = 0; 21643f03ced8SAlex Deucher break; 21653f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 21663f03ced8SAlex Deucher if (dig->linkb) 21678f0fc088SDave Airlie enc_idx = 3; 21683f03ced8SAlex Deucher else 21698f0fc088SDave Airlie enc_idx = 2; 21703f03ced8SAlex Deucher break; 21713f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 21723f03ced8SAlex Deucher if (dig->linkb) 21738f0fc088SDave Airlie enc_idx = 5; 21743f03ced8SAlex Deucher else 21758f0fc088SDave Airlie enc_idx = 4; 21763f03ced8SAlex Deucher break; 21773f03ced8SAlex Deucher } 21783f03ced8SAlex Deucher } 21798f0fc088SDave Airlie goto assigned; 21803f03ced8SAlex Deucher } 21813f03ced8SAlex Deucher 2182564d8a2cSMario Kleiner /* 2183564d8a2cSMario Kleiner * On DCE32 any encoder can drive any block so usually just use crtc id, 2184564d8a2cSMario Kleiner * but Apple thinks different at least on iMac10,1, so there use linkb, 2185564d8a2cSMario Kleiner * otherwise the internal eDP panel will stay dark. 2186564d8a2cSMario Kleiner */ 21873f03ced8SAlex Deucher if (ASIC_IS_DCE32(rdev)) { 2188564d8a2cSMario Kleiner if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1")) 2189564d8a2cSMario Kleiner enc_idx = (dig->linkb) ? 1 : 0; 2190564d8a2cSMario Kleiner else 21918f0fc088SDave Airlie enc_idx = radeon_crtc->crtc_id; 2192564d8a2cSMario Kleiner 21938f0fc088SDave Airlie goto assigned; 21943f03ced8SAlex Deucher } 21953f03ced8SAlex Deucher 21963f03ced8SAlex Deucher /* on DCE3 - LVTMA can only be driven by DIGB */ 21973f03ced8SAlex Deucher list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { 21983f03ced8SAlex Deucher struct radeon_encoder *radeon_test_encoder; 21993f03ced8SAlex Deucher 22003f03ced8SAlex Deucher if (encoder == test_encoder) 22013f03ced8SAlex Deucher continue; 22023f03ced8SAlex Deucher 22033f03ced8SAlex Deucher if (!radeon_encoder_is_digital(test_encoder)) 22043f03ced8SAlex Deucher continue; 22053f03ced8SAlex Deucher 22063f03ced8SAlex Deucher radeon_test_encoder = to_radeon_encoder(test_encoder); 22073f03ced8SAlex Deucher dig = radeon_test_encoder->enc_priv; 22083f03ced8SAlex Deucher 22093f03ced8SAlex Deucher if (dig->dig_encoder >= 0) 22103f03ced8SAlex Deucher dig_enc_in_use |= (1 << dig->dig_encoder); 22113f03ced8SAlex Deucher } 22123f03ced8SAlex Deucher 22133f03ced8SAlex Deucher if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { 22143f03ced8SAlex Deucher if (dig_enc_in_use & 0x2) 22153f03ced8SAlex Deucher DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n"); 22163f03ced8SAlex Deucher return 1; 22173f03ced8SAlex Deucher } 22183f03ced8SAlex Deucher if (!(dig_enc_in_use & 1)) 22193f03ced8SAlex Deucher return 0; 22203f03ced8SAlex Deucher return 1; 22218f0fc088SDave Airlie 22228f0fc088SDave Airlie assigned: 22238f0fc088SDave Airlie if (enc_idx == -1) { 22248f0fc088SDave Airlie DRM_ERROR("Got encoder index incorrect - returning 0\n"); 22258f0fc088SDave Airlie return 0; 22268f0fc088SDave Airlie } 22273c20d544SWambui Karuga if (rdev->mode_info.active_encoders & (1 << enc_idx)) 22288f0fc088SDave Airlie DRM_ERROR("chosen encoder in use %d\n", enc_idx); 22293c20d544SWambui Karuga 22308f0fc088SDave Airlie rdev->mode_info.active_encoders |= (1 << enc_idx); 22318f0fc088SDave Airlie return enc_idx; 22323f03ced8SAlex Deucher } 22333f03ced8SAlex Deucher 22343f03ced8SAlex Deucher /* This only needs to be called once at startup */ 22353f03ced8SAlex Deucher void 22363f03ced8SAlex Deucher radeon_atom_encoder_init(struct radeon_device *rdev) 22373f03ced8SAlex Deucher { 22383f03ced8SAlex Deucher struct drm_device *dev = rdev->ddev; 22393f03ced8SAlex Deucher struct drm_encoder *encoder; 22403f03ced8SAlex Deucher 22413f03ced8SAlex Deucher list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 22423f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 22433f03ced8SAlex Deucher struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 22443f03ced8SAlex Deucher 22453f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 22463f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 22473f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 22483f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2249e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 22503f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 22513f03ced8SAlex Deucher atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); 22523f03ced8SAlex Deucher break; 22533f03ced8SAlex Deucher default: 22543f03ced8SAlex Deucher break; 22553f03ced8SAlex Deucher } 22563f03ced8SAlex Deucher 22571d3949c4SAlex Deucher if (ext_encoder && (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))) 22583f03ced8SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 22593f03ced8SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); 22603f03ced8SAlex Deucher } 22613f03ced8SAlex Deucher } 22623f03ced8SAlex Deucher 22633f03ced8SAlex Deucher static void 22643f03ced8SAlex Deucher radeon_atom_encoder_mode_set(struct drm_encoder *encoder, 22653f03ced8SAlex Deucher struct drm_display_mode *mode, 22663f03ced8SAlex Deucher struct drm_display_mode *adjusted_mode) 22673f03ced8SAlex Deucher { 22683f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 22693f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 22703f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 22713473f542SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 22726f945693SSlava Grigorev int encoder_mode; 22733f03ced8SAlex Deucher 22743f03ced8SAlex Deucher radeon_encoder->pixel_clock = adjusted_mode->clock; 22753f03ced8SAlex Deucher 22768d1af57aSAlex Deucher /* need to call this here rather than in prepare() since we need some crtc info */ 22778d1af57aSAlex Deucher radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 22788d1af57aSAlex Deucher 22793f03ced8SAlex Deucher if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { 22803f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) 22813f03ced8SAlex Deucher atombios_yuv_setup(encoder, true); 22823f03ced8SAlex Deucher else 22833f03ced8SAlex Deucher atombios_yuv_setup(encoder, false); 22843f03ced8SAlex Deucher } 22853f03ced8SAlex Deucher 22863f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 22873f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 22883f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 22893f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 22903f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 22913f03ced8SAlex Deucher atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 22923f03ced8SAlex Deucher break; 22933f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 22943f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 22953f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2296e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 22973f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 22988d1af57aSAlex Deucher /* handled in dpms */ 22993f03ced8SAlex Deucher break; 23003f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 23013f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 23023f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 23033f03ced8SAlex Deucher atombios_dvo_setup(encoder, ATOM_ENABLE); 23043f03ced8SAlex Deucher break; 23053f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 23063f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 23073f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 23083f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 23093f03ced8SAlex Deucher atombios_dac_setup(encoder, ATOM_ENABLE); 23103f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) { 23113f03ced8SAlex Deucher if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 23123f03ced8SAlex Deucher atombios_tv_setup(encoder, ATOM_ENABLE); 23133f03ced8SAlex Deucher else 23143f03ced8SAlex Deucher atombios_tv_setup(encoder, ATOM_DISABLE); 23153f03ced8SAlex Deucher } 23163f03ced8SAlex Deucher break; 23173f03ced8SAlex Deucher } 23183f03ced8SAlex Deucher 23193f03ced8SAlex Deucher atombios_apply_encoder_quirks(encoder, adjusted_mode); 23205c046a57SAlex Deucher 23215c046a57SAlex Deucher encoder_mode = atombios_get_encoder_mode(encoder); 23225c046a57SAlex Deucher if (connector && (radeon_audio != 0) && 23235c046a57SAlex Deucher ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || 23247726e72bSAlex Deucher ENCODER_MODE_IS_DP(encoder_mode))) 23255c046a57SAlex Deucher radeon_audio_mode_set(encoder, adjusted_mode); 23263f03ced8SAlex Deucher } 23273f03ced8SAlex Deucher 23283f03ced8SAlex Deucher static bool 23293f03ced8SAlex Deucher atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) 23303f03ced8SAlex Deucher { 23313f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 23323f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 23333f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 23343f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 23353f03ced8SAlex Deucher 23363f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | 23373f03ced8SAlex Deucher ATOM_DEVICE_CV_SUPPORT | 23383f03ced8SAlex Deucher ATOM_DEVICE_CRT_SUPPORT)) { 23393f03ced8SAlex Deucher DAC_LOAD_DETECTION_PS_ALLOCATION args; 23403f03ced8SAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 23413f03ced8SAlex Deucher uint8_t frev, crev; 23423f03ced8SAlex Deucher 23433f03ced8SAlex Deucher memset(&args, 0, sizeof(args)); 23443f03ced8SAlex Deucher 23453f03ced8SAlex Deucher if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) 23463f03ced8SAlex Deucher return false; 23473f03ced8SAlex Deucher 23483f03ced8SAlex Deucher args.sDacload.ucMisc = 0; 23493f03ced8SAlex Deucher 23503f03ced8SAlex Deucher if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || 23513f03ced8SAlex Deucher (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) 23523f03ced8SAlex Deucher args.sDacload.ucDacType = ATOM_DAC_A; 23533f03ced8SAlex Deucher else 23543f03ced8SAlex Deucher args.sDacload.ucDacType = ATOM_DAC_B; 23553f03ced8SAlex Deucher 23563f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) 23573f03ced8SAlex Deucher args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); 23583f03ced8SAlex Deucher else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) 23593f03ced8SAlex Deucher args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); 23603f03ced8SAlex Deucher else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 23613f03ced8SAlex Deucher args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); 23623f03ced8SAlex Deucher if (crev >= 3) 23633f03ced8SAlex Deucher args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 23643f03ced8SAlex Deucher } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 23653f03ced8SAlex Deucher args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); 23663f03ced8SAlex Deucher if (crev >= 3) 23673f03ced8SAlex Deucher args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 23683f03ced8SAlex Deucher } 23693f03ced8SAlex Deucher 23703f03ced8SAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 23713f03ced8SAlex Deucher 23723f03ced8SAlex Deucher return true; 23733f03ced8SAlex Deucher } else 23743f03ced8SAlex Deucher return false; 23753f03ced8SAlex Deucher } 23763f03ced8SAlex Deucher 23773f03ced8SAlex Deucher static enum drm_connector_status 23783f03ced8SAlex Deucher radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 23793f03ced8SAlex Deucher { 23803f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 23813f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 23823f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 23833f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 23843f03ced8SAlex Deucher uint32_t bios_0_scratch; 23853f03ced8SAlex Deucher 23863f03ced8SAlex Deucher if (!atombios_dac_load_detect(encoder, connector)) { 23873f03ced8SAlex Deucher DRM_DEBUG_KMS("detect returned false \n"); 23883f03ced8SAlex Deucher return connector_status_unknown; 23893f03ced8SAlex Deucher } 23903f03ced8SAlex Deucher 23913f03ced8SAlex Deucher if (rdev->family >= CHIP_R600) 23923f03ced8SAlex Deucher bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 23933f03ced8SAlex Deucher else 23943f03ced8SAlex Deucher bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); 23953f03ced8SAlex Deucher 23963f03ced8SAlex Deucher DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 23973f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 23983f03ced8SAlex Deucher if (bios_0_scratch & ATOM_S0_CRT1_MASK) 23993f03ced8SAlex Deucher return connector_status_connected; 24003f03ced8SAlex Deucher } 24013f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 24023f03ced8SAlex Deucher if (bios_0_scratch & ATOM_S0_CRT2_MASK) 24033f03ced8SAlex Deucher return connector_status_connected; 24043f03ced8SAlex Deucher } 24053f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 24063f03ced8SAlex Deucher if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 24073f03ced8SAlex Deucher return connector_status_connected; 24083f03ced8SAlex Deucher } 24093f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 24103f03ced8SAlex Deucher if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 24113f03ced8SAlex Deucher return connector_status_connected; /* CTV */ 24123f03ced8SAlex Deucher else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 24133f03ced8SAlex Deucher return connector_status_connected; /* STV */ 24143f03ced8SAlex Deucher } 24153f03ced8SAlex Deucher return connector_status_disconnected; 24163f03ced8SAlex Deucher } 24173f03ced8SAlex Deucher 24183f03ced8SAlex Deucher static enum drm_connector_status 24193f03ced8SAlex Deucher radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) 24203f03ced8SAlex Deucher { 24213f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 24223f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 24233f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 24243f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 24253f03ced8SAlex Deucher struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 24263f03ced8SAlex Deucher u32 bios_0_scratch; 24273f03ced8SAlex Deucher 24283f03ced8SAlex Deucher if (!ASIC_IS_DCE4(rdev)) 24293f03ced8SAlex Deucher return connector_status_unknown; 24303f03ced8SAlex Deucher 24313f03ced8SAlex Deucher if (!ext_encoder) 24323f03ced8SAlex Deucher return connector_status_unknown; 24333f03ced8SAlex Deucher 24343f03ced8SAlex Deucher if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) 24353f03ced8SAlex Deucher return connector_status_unknown; 24363f03ced8SAlex Deucher 24373f03ced8SAlex Deucher /* load detect on the dp bridge */ 24383f03ced8SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 24393f03ced8SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); 24403f03ced8SAlex Deucher 24413f03ced8SAlex Deucher bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); 24423f03ced8SAlex Deucher 24433f03ced8SAlex Deucher DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); 24443f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { 24453f03ced8SAlex Deucher if (bios_0_scratch & ATOM_S0_CRT1_MASK) 24463f03ced8SAlex Deucher return connector_status_connected; 24473f03ced8SAlex Deucher } 24483f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { 24493f03ced8SAlex Deucher if (bios_0_scratch & ATOM_S0_CRT2_MASK) 24503f03ced8SAlex Deucher return connector_status_connected; 24513f03ced8SAlex Deucher } 24523f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { 24533f03ced8SAlex Deucher if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) 24543f03ced8SAlex Deucher return connector_status_connected; 24553f03ced8SAlex Deucher } 24563f03ced8SAlex Deucher if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { 24573f03ced8SAlex Deucher if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) 24583f03ced8SAlex Deucher return connector_status_connected; /* CTV */ 24593f03ced8SAlex Deucher else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) 24603f03ced8SAlex Deucher return connector_status_connected; /* STV */ 24613f03ced8SAlex Deucher } 24623f03ced8SAlex Deucher return connector_status_disconnected; 24633f03ced8SAlex Deucher } 24643f03ced8SAlex Deucher 24653f03ced8SAlex Deucher void 24663f03ced8SAlex Deucher radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) 24673f03ced8SAlex Deucher { 24683f03ced8SAlex Deucher struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); 24693f03ced8SAlex Deucher 24703f03ced8SAlex Deucher if (ext_encoder) 24713f03ced8SAlex Deucher /* ddc_setup on the dp bridge */ 24723f03ced8SAlex Deucher atombios_external_encoder_setup(encoder, ext_encoder, 24733f03ced8SAlex Deucher EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); 24743f03ced8SAlex Deucher 24753f03ced8SAlex Deucher } 24763f03ced8SAlex Deucher 24773f03ced8SAlex Deucher static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) 24783f03ced8SAlex Deucher { 2479cfcbd6d3SRafał Miłecki struct radeon_device *rdev = encoder->dev->dev_private; 24803f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 24813f03ced8SAlex Deucher struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 24823f03ced8SAlex Deucher 24833f03ced8SAlex Deucher if ((radeon_encoder->active_device & 24843f03ced8SAlex Deucher (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || 24853f03ced8SAlex Deucher (radeon_encoder_get_dp_bridge_encoder_id(encoder) != 24863f03ced8SAlex Deucher ENCODER_OBJECT_ID_NONE)) { 24873f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 2488cfcbd6d3SRafał Miłecki if (dig) { 24898f0fc088SDave Airlie if (dig->dig_encoder >= 0) 24908f0fc088SDave Airlie radeon_atom_release_dig_encoder(rdev, dig->dig_encoder); 24918f0fc088SDave Airlie dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1); 2492cfcbd6d3SRafał Miłecki if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) { 2493cfcbd6d3SRafał Miłecki if (rdev->family >= CHIP_R600) 2494cfcbd6d3SRafał Miłecki dig->afmt = rdev->mode_info.afmt[dig->dig_encoder]; 2495cfcbd6d3SRafał Miłecki else 2496cfcbd6d3SRafał Miłecki /* RS600/690/740 have only 1 afmt block */ 2497cfcbd6d3SRafał Miłecki dig->afmt = rdev->mode_info.afmt[0]; 2498cfcbd6d3SRafał Miłecki } 2499cfcbd6d3SRafał Miłecki } 25003f03ced8SAlex Deucher } 25013f03ced8SAlex Deucher 25023f03ced8SAlex Deucher radeon_atom_output_lock(encoder, true); 25033f03ced8SAlex Deucher 25043f03ced8SAlex Deucher if (connector) { 25053f03ced8SAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 25063f03ced8SAlex Deucher 25073f03ced8SAlex Deucher /* select the clock/data port if it uses a router */ 25083f03ced8SAlex Deucher if (radeon_connector->router.cd_valid) 25093f03ced8SAlex Deucher radeon_router_select_cd_port(radeon_connector); 25103f03ced8SAlex Deucher 25113f03ced8SAlex Deucher /* turn eDP panel on for mode set */ 25123f03ced8SAlex Deucher if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) 25133f03ced8SAlex Deucher atombios_set_edp_panel_power(connector, 25143f03ced8SAlex Deucher ATOM_TRANSMITTER_ACTION_POWER_ON); 25153f03ced8SAlex Deucher } 25163f03ced8SAlex Deucher 25173f03ced8SAlex Deucher /* this is needed for the pll/ss setup to work correctly in some cases */ 25183f03ced8SAlex Deucher atombios_set_encoder_crtc_source(encoder); 2519134b480fSAlex Deucher /* set up the FMT blocks */ 2520134b480fSAlex Deucher if (ASIC_IS_DCE8(rdev)) 2521134b480fSAlex Deucher dce8_program_fmt(encoder); 2522134b480fSAlex Deucher else if (ASIC_IS_DCE4(rdev)) 2523134b480fSAlex Deucher dce4_program_fmt(encoder); 2524134b480fSAlex Deucher else if (ASIC_IS_DCE3(rdev)) 2525134b480fSAlex Deucher dce3_program_fmt(encoder); 2526134b480fSAlex Deucher else if (ASIC_IS_AVIVO(rdev)) 2527134b480fSAlex Deucher avivo_program_fmt(encoder); 25283f03ced8SAlex Deucher } 25293f03ced8SAlex Deucher 25303f03ced8SAlex Deucher static void radeon_atom_encoder_commit(struct drm_encoder *encoder) 25313f03ced8SAlex Deucher { 25328d1af57aSAlex Deucher /* need to call this here as we need the crtc set up */ 25333f03ced8SAlex Deucher radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 25343f03ced8SAlex Deucher radeon_atom_output_lock(encoder, false); 25353f03ced8SAlex Deucher } 25363f03ced8SAlex Deucher 25373f03ced8SAlex Deucher static void radeon_atom_encoder_disable(struct drm_encoder *encoder) 25383f03ced8SAlex Deucher { 25393f03ced8SAlex Deucher struct drm_device *dev = encoder->dev; 25403f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 25413f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 25423f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig; 25433f03ced8SAlex Deucher 25443f03ced8SAlex Deucher /* check for pre-DCE3 cards with shared encoders; 25453f03ced8SAlex Deucher * can't really use the links individually, so don't disable 25463f03ced8SAlex Deucher * the encoder if it's in use by another connector 25473f03ced8SAlex Deucher */ 25483f03ced8SAlex Deucher if (!ASIC_IS_DCE3(rdev)) { 25493f03ced8SAlex Deucher struct drm_encoder *other_encoder; 25503f03ced8SAlex Deucher struct radeon_encoder *other_radeon_encoder; 25513f03ced8SAlex Deucher 25523f03ced8SAlex Deucher list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { 25533f03ced8SAlex Deucher other_radeon_encoder = to_radeon_encoder(other_encoder); 25543f03ced8SAlex Deucher if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && 25553f03ced8SAlex Deucher drm_helper_encoder_in_use(other_encoder)) 25563f03ced8SAlex Deucher goto disable_done; 25573f03ced8SAlex Deucher } 25583f03ced8SAlex Deucher } 25593f03ced8SAlex Deucher 25603f03ced8SAlex Deucher radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 25613f03ced8SAlex Deucher 25623f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 25633f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 25643f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 25653f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 25663f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 25673f03ced8SAlex Deucher atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE); 25683f03ced8SAlex Deucher break; 25693f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 25703f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 25713f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2572e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 25733f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 25748d1af57aSAlex Deucher /* handled in dpms */ 25753f03ced8SAlex Deucher break; 25763f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 25773f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 25783f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 25793f03ced8SAlex Deucher atombios_dvo_setup(encoder, ATOM_DISABLE); 25803f03ced8SAlex Deucher break; 25813f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 25823f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 25833f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 25843f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 25853f03ced8SAlex Deucher atombios_dac_setup(encoder, ATOM_DISABLE); 25863f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 25873f03ced8SAlex Deucher atombios_tv_setup(encoder, ATOM_DISABLE); 25883f03ced8SAlex Deucher break; 25893f03ced8SAlex Deucher } 25903f03ced8SAlex Deucher 25913f03ced8SAlex Deucher disable_done: 25923f03ced8SAlex Deucher if (radeon_encoder_is_digital(encoder)) { 25938f0fc088SDave Airlie if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { 25948f0fc088SDave Airlie if (rdev->asic->display.hdmi_enable) 25958f0fc088SDave Airlie radeon_hdmi_enable(rdev, encoder, false); 25963f03ced8SAlex Deucher } 25978f0fc088SDave Airlie if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) { 25988f0fc088SDave Airlie dig = radeon_encoder->enc_priv; 25998f0fc088SDave Airlie radeon_atom_release_dig_encoder(rdev, dig->dig_encoder); 26008f0fc088SDave Airlie dig->dig_encoder = -1; 26018f0fc088SDave Airlie radeon_encoder->active_device = 0; 26028f0fc088SDave Airlie } 26038f0fc088SDave Airlie } else 26043f03ced8SAlex Deucher radeon_encoder->active_device = 0; 26053f03ced8SAlex Deucher } 26063f03ced8SAlex Deucher 26073f03ced8SAlex Deucher /* these are handled by the primary encoders */ 26083f03ced8SAlex Deucher static void radeon_atom_ext_prepare(struct drm_encoder *encoder) 26093f03ced8SAlex Deucher { 26103f03ced8SAlex Deucher 26113f03ced8SAlex Deucher } 26123f03ced8SAlex Deucher 26133f03ced8SAlex Deucher static void radeon_atom_ext_commit(struct drm_encoder *encoder) 26143f03ced8SAlex Deucher { 26153f03ced8SAlex Deucher 26163f03ced8SAlex Deucher } 26173f03ced8SAlex Deucher 26183f03ced8SAlex Deucher static void 26193f03ced8SAlex Deucher radeon_atom_ext_mode_set(struct drm_encoder *encoder, 26203f03ced8SAlex Deucher struct drm_display_mode *mode, 26213f03ced8SAlex Deucher struct drm_display_mode *adjusted_mode) 26223f03ced8SAlex Deucher { 26233f03ced8SAlex Deucher 26243f03ced8SAlex Deucher } 26253f03ced8SAlex Deucher 26263f03ced8SAlex Deucher static void radeon_atom_ext_disable(struct drm_encoder *encoder) 26273f03ced8SAlex Deucher { 26283f03ced8SAlex Deucher 26293f03ced8SAlex Deucher } 26303f03ced8SAlex Deucher 26313f03ced8SAlex Deucher static void 26323f03ced8SAlex Deucher radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) 26333f03ced8SAlex Deucher { 26343f03ced8SAlex Deucher 26353f03ced8SAlex Deucher } 26363f03ced8SAlex Deucher 26373f03ced8SAlex Deucher static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { 26383f03ced8SAlex Deucher .dpms = radeon_atom_ext_dpms, 26393f03ced8SAlex Deucher .prepare = radeon_atom_ext_prepare, 26403f03ced8SAlex Deucher .mode_set = radeon_atom_ext_mode_set, 26413f03ced8SAlex Deucher .commit = radeon_atom_ext_commit, 26423f03ced8SAlex Deucher .disable = radeon_atom_ext_disable, 26433f03ced8SAlex Deucher /* no detect for TMDS/LVDS yet */ 26443f03ced8SAlex Deucher }; 26453f03ced8SAlex Deucher 26463f03ced8SAlex Deucher static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { 26473f03ced8SAlex Deucher .dpms = radeon_atom_encoder_dpms, 26483f03ced8SAlex Deucher .mode_fixup = radeon_atom_mode_fixup, 26493f03ced8SAlex Deucher .prepare = radeon_atom_encoder_prepare, 26503f03ced8SAlex Deucher .mode_set = radeon_atom_encoder_mode_set, 26513f03ced8SAlex Deucher .commit = radeon_atom_encoder_commit, 26523f03ced8SAlex Deucher .disable = radeon_atom_encoder_disable, 26533f03ced8SAlex Deucher .detect = radeon_atom_dig_detect, 26543f03ced8SAlex Deucher }; 26553f03ced8SAlex Deucher 26563f03ced8SAlex Deucher static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { 26573f03ced8SAlex Deucher .dpms = radeon_atom_encoder_dpms, 26583f03ced8SAlex Deucher .mode_fixup = radeon_atom_mode_fixup, 26593f03ced8SAlex Deucher .prepare = radeon_atom_encoder_prepare, 26603f03ced8SAlex Deucher .mode_set = radeon_atom_encoder_mode_set, 26613f03ced8SAlex Deucher .commit = radeon_atom_encoder_commit, 26623f03ced8SAlex Deucher .detect = radeon_atom_dac_detect, 26633f03ced8SAlex Deucher }; 26643f03ced8SAlex Deucher 26653f03ced8SAlex Deucher void radeon_enc_destroy(struct drm_encoder *encoder) 26663f03ced8SAlex Deucher { 26673f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 2668f3728734SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 2669f3728734SAlex Deucher radeon_atom_backlight_exit(radeon_encoder); 26703f03ced8SAlex Deucher kfree(radeon_encoder->enc_priv); 26713f03ced8SAlex Deucher drm_encoder_cleanup(encoder); 26723f03ced8SAlex Deucher kfree(radeon_encoder); 26733f03ced8SAlex Deucher } 26743f03ced8SAlex Deucher 26753f03ced8SAlex Deucher static const struct drm_encoder_funcs radeon_atom_enc_funcs = { 26763f03ced8SAlex Deucher .destroy = radeon_enc_destroy, 26773f03ced8SAlex Deucher }; 26783f03ced8SAlex Deucher 26791109ca09SLauri Kasanen static struct radeon_encoder_atom_dac * 26803f03ced8SAlex Deucher radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) 26813f03ced8SAlex Deucher { 26823f03ced8SAlex Deucher struct drm_device *dev = radeon_encoder->base.dev; 26833f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 26843f03ced8SAlex Deucher struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); 26853f03ced8SAlex Deucher 26863f03ced8SAlex Deucher if (!dac) 26873f03ced8SAlex Deucher return NULL; 26883f03ced8SAlex Deucher 26893f03ced8SAlex Deucher dac->tv_std = radeon_atombios_get_tv_info(rdev); 26903f03ced8SAlex Deucher return dac; 26913f03ced8SAlex Deucher } 26923f03ced8SAlex Deucher 26931109ca09SLauri Kasanen static struct radeon_encoder_atom_dig * 26943f03ced8SAlex Deucher radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) 26953f03ced8SAlex Deucher { 26963f03ced8SAlex Deucher int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 26973f03ced8SAlex Deucher struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); 26983f03ced8SAlex Deucher 26993f03ced8SAlex Deucher if (!dig) 27003f03ced8SAlex Deucher return NULL; 27013f03ced8SAlex Deucher 27023f03ced8SAlex Deucher /* coherent mode by default */ 27033f03ced8SAlex Deucher dig->coherent_mode = true; 27043f03ced8SAlex Deucher dig->dig_encoder = -1; 27053f03ced8SAlex Deucher 27063f03ced8SAlex Deucher if (encoder_enum == 2) 27073f03ced8SAlex Deucher dig->linkb = true; 27083f03ced8SAlex Deucher else 27093f03ced8SAlex Deucher dig->linkb = false; 27103f03ced8SAlex Deucher 27113f03ced8SAlex Deucher return dig; 27123f03ced8SAlex Deucher } 27133f03ced8SAlex Deucher 27143f03ced8SAlex Deucher void 27153f03ced8SAlex Deucher radeon_add_atom_encoder(struct drm_device *dev, 27163f03ced8SAlex Deucher uint32_t encoder_enum, 27173f03ced8SAlex Deucher uint32_t supported_device, 27183f03ced8SAlex Deucher u16 caps) 27193f03ced8SAlex Deucher { 27203f03ced8SAlex Deucher struct radeon_device *rdev = dev->dev_private; 27213f03ced8SAlex Deucher struct drm_encoder *encoder; 27223f03ced8SAlex Deucher struct radeon_encoder *radeon_encoder; 27233f03ced8SAlex Deucher 27243f03ced8SAlex Deucher /* see if we already added it */ 27253f03ced8SAlex Deucher list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 27263f03ced8SAlex Deucher radeon_encoder = to_radeon_encoder(encoder); 27273f03ced8SAlex Deucher if (radeon_encoder->encoder_enum == encoder_enum) { 27283f03ced8SAlex Deucher radeon_encoder->devices |= supported_device; 27293f03ced8SAlex Deucher return; 27303f03ced8SAlex Deucher } 27313f03ced8SAlex Deucher 27323f03ced8SAlex Deucher } 27333f03ced8SAlex Deucher 27343f03ced8SAlex Deucher /* add a new one */ 27353f03ced8SAlex Deucher radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); 27363f03ced8SAlex Deucher if (!radeon_encoder) 27373f03ced8SAlex Deucher return; 27383f03ced8SAlex Deucher 27393f03ced8SAlex Deucher encoder = &radeon_encoder->base; 27403f03ced8SAlex Deucher switch (rdev->num_crtc) { 27413f03ced8SAlex Deucher case 1: 27423f03ced8SAlex Deucher encoder->possible_crtcs = 0x1; 27433f03ced8SAlex Deucher break; 27443f03ced8SAlex Deucher case 2: 27453f03ced8SAlex Deucher default: 27463f03ced8SAlex Deucher encoder->possible_crtcs = 0x3; 27473f03ced8SAlex Deucher break; 27483f03ced8SAlex Deucher case 4: 27493f03ced8SAlex Deucher encoder->possible_crtcs = 0xf; 27503f03ced8SAlex Deucher break; 27513f03ced8SAlex Deucher case 6: 27523f03ced8SAlex Deucher encoder->possible_crtcs = 0x3f; 27533f03ced8SAlex Deucher break; 27543f03ced8SAlex Deucher } 27553f03ced8SAlex Deucher 27563f03ced8SAlex Deucher radeon_encoder->enc_priv = NULL; 27573f03ced8SAlex Deucher 27583f03ced8SAlex Deucher radeon_encoder->encoder_enum = encoder_enum; 27593f03ced8SAlex Deucher radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 27603f03ced8SAlex Deucher radeon_encoder->devices = supported_device; 27613f03ced8SAlex Deucher radeon_encoder->rmx_type = RMX_OFF; 27623f03ced8SAlex Deucher radeon_encoder->underscan_type = UNDERSCAN_OFF; 27633f03ced8SAlex Deucher radeon_encoder->is_ext_encoder = false; 27643f03ced8SAlex Deucher radeon_encoder->caps = caps; 27653f03ced8SAlex Deucher 27663f03ced8SAlex Deucher switch (radeon_encoder->encoder_id) { 27673f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVDS: 27683f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 27693f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 27703f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 27713f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 27723f03ced8SAlex Deucher radeon_encoder->rmx_type = RMX_FULL; 277313a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 277413a3d91fSVille Syrjälä DRM_MODE_ENCODER_LVDS, NULL); 27753f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 27763f03ced8SAlex Deucher } else { 277713a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 277813a3d91fSVille Syrjälä DRM_MODE_ENCODER_TMDS, NULL); 27793f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 27803f03ced8SAlex Deucher } 27813f03ced8SAlex Deucher drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 27823f03ced8SAlex Deucher break; 27833f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC1: 278413a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 278513a3d91fSVille Syrjälä DRM_MODE_ENCODER_DAC, NULL); 27863f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 27873f03ced8SAlex Deucher drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 27883f03ced8SAlex Deucher break; 27893f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DAC2: 27903f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 27913f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 279213a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 279313a3d91fSVille Syrjälä DRM_MODE_ENCODER_TVDAC, NULL); 27943f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); 27953f03ced8SAlex Deucher drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); 27963f03ced8SAlex Deucher break; 27973f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DVO1: 27983f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 27993f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_DDI: 28003f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 28013f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 28023f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 28033f03ced8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2804e68adef8SAlex Deucher case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 28053f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { 28063f03ced8SAlex Deucher radeon_encoder->rmx_type = RMX_FULL; 280713a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 280813a3d91fSVille Syrjälä DRM_MODE_ENCODER_LVDS, NULL); 28093f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 28103f03ced8SAlex Deucher } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { 281113a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 281213a3d91fSVille Syrjälä DRM_MODE_ENCODER_DAC, NULL); 28133f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 28143f03ced8SAlex Deucher } else { 281513a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 281613a3d91fSVille Syrjälä DRM_MODE_ENCODER_TMDS, NULL); 28173f03ced8SAlex Deucher radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); 28183f03ced8SAlex Deucher } 28193f03ced8SAlex Deucher drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); 28203f03ced8SAlex Deucher break; 28213f03ced8SAlex Deucher case ENCODER_OBJECT_ID_SI170B: 28223f03ced8SAlex Deucher case ENCODER_OBJECT_ID_CH7303: 28233f03ced8SAlex Deucher case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 28243f03ced8SAlex Deucher case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 28253f03ced8SAlex Deucher case ENCODER_OBJECT_ID_TITFP513: 28263f03ced8SAlex Deucher case ENCODER_OBJECT_ID_VT1623: 28273f03ced8SAlex Deucher case ENCODER_OBJECT_ID_HDMI_SI1930: 28283f03ced8SAlex Deucher case ENCODER_OBJECT_ID_TRAVIS: 28293f03ced8SAlex Deucher case ENCODER_OBJECT_ID_NUTMEG: 28303f03ced8SAlex Deucher /* these are handled by the primary encoders */ 28313f03ced8SAlex Deucher radeon_encoder->is_ext_encoder = true; 28323f03ced8SAlex Deucher if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) 283313a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 283413a3d91fSVille Syrjälä DRM_MODE_ENCODER_LVDS, NULL); 28353f03ced8SAlex Deucher else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) 283613a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 283713a3d91fSVille Syrjälä DRM_MODE_ENCODER_DAC, NULL); 28383f03ced8SAlex Deucher else 283913a3d91fSVille Syrjälä drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, 284013a3d91fSVille Syrjälä DRM_MODE_ENCODER_TMDS, NULL); 28413f03ced8SAlex Deucher drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs); 28423f03ced8SAlex Deucher break; 28433f03ced8SAlex Deucher } 28443f03ced8SAlex Deucher } 2845