| File: | dev/pci/drm/radeon/atombios_encoders.c |
| Warning: | line 2785, column 1 Potential leak of memory pointed to by 'radeon_encoder' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | |||
| 2 | * Copyright 2007-11 Advanced Micro Devices, Inc. | |||
| 3 | * Copyright 2008 Red Hat Inc. | |||
| 4 | * | |||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
| 6 | * copy of this software and associated documentation files (the "Software"), | |||
| 7 | * to deal in the Software without restriction, including without limitation | |||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | |||
| 10 | * Software is furnished to do so, subject to the following conditions: | |||
| 11 | * | |||
| 12 | * The above copyright notice and this permission notice shall be included in | |||
| 13 | * all copies or substantial portions of the Software. | |||
| 14 | * | |||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | |||
| 22 | * | |||
| 23 | * Authors: Dave Airlie | |||
| 24 | * Alex Deucher | |||
| 25 | */ | |||
| 26 | ||||
| 27 | #include <linux/backlight.h> | |||
| 28 | #include <linux/dmi.h> | |||
| 29 | #include <linux/pci.h> | |||
| 30 | ||||
| 31 | #include <drm/drm_crtc_helper.h> | |||
| 32 | #include <drm/drm_file.h> | |||
| 33 | #include <drm/radeon_drm.h> | |||
| 34 | ||||
| 35 | #include <acpi/video.h> | |||
| 36 | ||||
| 37 | #include "atom.h" | |||
| 38 | #include "radeon_atombios.h" | |||
| 39 | #include "radeon.h" | |||
| 40 | #include "radeon_asic.h" | |||
| 41 | #include "radeon_audio.h" | |||
| 42 | ||||
| 43 | extern int atom_debug; | |||
| 44 | ||||
| 45 | static u8 | |||
| 46 | radeon_atom_get_backlight_level_from_reg(struct radeon_device *rdev) | |||
| 47 | { | |||
| 48 | u8 backlight_level; | |||
| 49 | u32 bios_2_scratch; | |||
| 50 | ||||
| 51 | if (rdev->family >= CHIP_R600) | |||
| 52 | bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH)r100_mm_rreg(rdev, (0x172c), 0); | |||
| 53 | else | |||
| 54 | bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH)r100_mm_rreg(rdev, (0x0018), 0); | |||
| 55 | ||||
| 56 | backlight_level = ((bios_2_scratch & ATOM_S2_CURRENT_BL_LEVEL_MASK0x0000FF00L) >> | |||
| 57 | ATOM_S2_CURRENT_BL_LEVEL_SHIFT8); | |||
| 58 | ||||
| 59 | return backlight_level; | |||
| 60 | } | |||
| 61 | ||||
| 62 | static void | |||
| 63 | radeon_atom_set_backlight_level_to_reg(struct radeon_device *rdev, | |||
| 64 | u8 backlight_level) | |||
| 65 | { | |||
| 66 | u32 bios_2_scratch; | |||
| 67 | ||||
| 68 | if (rdev->family >= CHIP_R600) | |||
| 69 | bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH)r100_mm_rreg(rdev, (0x172c), 0); | |||
| 70 | else | |||
| 71 | bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH)r100_mm_rreg(rdev, (0x0018), 0); | |||
| 72 | ||||
| 73 | bios_2_scratch &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK0x0000FF00L; | |||
| 74 | bios_2_scratch |= ((backlight_level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT8) & | |||
| 75 | ATOM_S2_CURRENT_BL_LEVEL_MASK0x0000FF00L); | |||
| 76 | ||||
| 77 | if (rdev->family >= CHIP_R600) | |||
| 78 | WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch)r100_mm_wreg(rdev, (0x172c), (bios_2_scratch), 0); | |||
| 79 | else | |||
| 80 | WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch)r100_mm_wreg(rdev, (0x0018), (bios_2_scratch), 0); | |||
| 81 | } | |||
| 82 | ||||
| 83 | u8 | |||
| 84 | atombios_get_backlight_level(struct radeon_encoder *radeon_encoder) | |||
| 85 | { | |||
| 86 | struct drm_device *dev = radeon_encoder->base.dev; | |||
| 87 | struct radeon_device *rdev = dev->dev_private; | |||
| 88 | ||||
| 89 | if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU0x0020)) | |||
| 90 | return 0; | |||
| 91 | ||||
| 92 | return radeon_atom_get_backlight_level_from_reg(rdev); | |||
| 93 | } | |||
| 94 | ||||
| 95 | void | |||
| 96 | atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) | |||
| 97 | { | |||
| 98 | struct drm_encoder *encoder = &radeon_encoder->base; | |||
| 99 | struct drm_device *dev = radeon_encoder->base.dev; | |||
| 100 | struct radeon_device *rdev = dev->dev_private; | |||
| 101 | struct radeon_encoder_atom_dig *dig; | |||
| 102 | DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATIONDISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS args; | |||
| 103 | int index; | |||
| 104 | ||||
| 105 | if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU0x0020)) | |||
| 106 | return; | |||
| 107 | ||||
| 108 | if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) && | |||
| 109 | radeon_encoder->enc_priv) { | |||
| 110 | dig = radeon_encoder->enc_priv; | |||
| 111 | dig->backlight_level = level; | |||
| 112 | radeon_atom_set_backlight_level_to_reg(rdev, dig->backlight_level); | |||
| 113 | ||||
| 114 | switch (radeon_encoder->encoder_id) { | |||
| 115 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 116 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 117 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, HW_Misc_Operation )/sizeof(USHORT)); | |||
| 118 | if (dig->backlight_level == 0) { | |||
| 119 | args.ucAction = ATOM_LCD_BLOFF(0 +2); | |||
| 120 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 121 | } else { | |||
| 122 | args.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL(1 +3); | |||
| 123 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 124 | args.ucAction = ATOM_LCD_BLON(1 +2); | |||
| 125 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 126 | } | |||
| 127 | break; | |||
| 128 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 129 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 130 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 131 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 132 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 133 | if (dig->backlight_level == 0) | |||
| 134 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF2, 0, 0); | |||
| 135 | else { | |||
| 136 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL4, 0, 0); | |||
| 137 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON3, 0, 0); | |||
| 138 | } | |||
| 139 | break; | |||
| 140 | default: | |||
| 141 | break; | |||
| 142 | } | |||
| 143 | } | |||
| 144 | } | |||
| 145 | ||||
| 146 | static u8 radeon_atom_bl_level(struct backlight_device *bd) | |||
| 147 | { | |||
| 148 | u8 level; | |||
| 149 | ||||
| 150 | /* Convert brightness to hardware level */ | |||
| 151 | if (bd->props.brightness < 0) | |||
| 152 | level = 0; | |||
| 153 | else if (bd->props.brightness > RADEON_MAX_BL_LEVEL0xFF) | |||
| 154 | level = RADEON_MAX_BL_LEVEL0xFF; | |||
| 155 | else | |||
| 156 | level = bd->props.brightness; | |||
| 157 | ||||
| 158 | return level; | |||
| 159 | } | |||
| 160 | ||||
| 161 | static int radeon_atom_backlight_update_status(struct backlight_device *bd) | |||
| 162 | { | |||
| 163 | struct radeon_backlight_privdata *pdata = bl_get_data(bd); | |||
| 164 | struct radeon_encoder *radeon_encoder = pdata->encoder; | |||
| 165 | ||||
| 166 | atombios_set_backlight_level(radeon_encoder, radeon_atom_bl_level(bd)); | |||
| 167 | ||||
| 168 | return 0; | |||
| 169 | } | |||
| 170 | ||||
| 171 | static int radeon_atom_backlight_get_brightness(struct backlight_device *bd) | |||
| 172 | { | |||
| 173 | struct radeon_backlight_privdata *pdata = bl_get_data(bd); | |||
| 174 | struct radeon_encoder *radeon_encoder = pdata->encoder; | |||
| 175 | struct drm_device *dev = radeon_encoder->base.dev; | |||
| 176 | struct radeon_device *rdev = dev->dev_private; | |||
| 177 | ||||
| 178 | return radeon_atom_get_backlight_level_from_reg(rdev); | |||
| 179 | } | |||
| 180 | ||||
| 181 | static const struct backlight_ops radeon_atom_backlight_ops = { | |||
| 182 | .get_brightness = radeon_atom_backlight_get_brightness, | |||
| 183 | .update_status = radeon_atom_backlight_update_status, | |||
| 184 | }; | |||
| 185 | ||||
| 186 | void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, | |||
| 187 | struct drm_connector *drm_connector) | |||
| 188 | { | |||
| 189 | struct drm_device *dev = radeon_encoder->base.dev; | |||
| 190 | struct radeon_device *rdev = dev->dev_private; | |||
| 191 | struct backlight_device *bd; | |||
| 192 | struct backlight_properties props; | |||
| 193 | struct radeon_backlight_privdata *pdata; | |||
| 194 | struct radeon_encoder_atom_dig *dig; | |||
| 195 | char bl_name[16]; | |||
| 196 | ||||
| 197 | /* Mac laptops with multiple GPUs use the gmux driver for backlight | |||
| 198 | * so don't register a backlight device | |||
| 199 | */ | |||
| 200 | if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE0x106b) && | |||
| 201 | (rdev->pdev->device == 0x6741) && | |||
| 202 | !dmi_match(DMI_PRODUCT_NAME, "iMac12,1")) | |||
| 203 | return; | |||
| 204 | ||||
| 205 | if (!radeon_encoder->enc_priv) | |||
| 206 | return; | |||
| 207 | ||||
| 208 | if (!rdev->is_atom_bios) | |||
| 209 | return; | |||
| 210 | ||||
| 211 | if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU0x0020)) | |||
| 212 | return; | |||
| 213 | ||||
| 214 | if (!acpi_video_backlight_use_native()) { | |||
| 215 | drm_info(dev, "Skipping radeon atom DIG backlight registration\n")do { } while(0); | |||
| 216 | return; | |||
| 217 | } | |||
| 218 | ||||
| 219 | pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL(0x0001 | 0x0004)); | |||
| 220 | if (!pdata) { | |||
| 221 | DRM_ERROR("Memory allocation failed\n")__drm_err("Memory allocation failed\n"); | |||
| 222 | goto error; | |||
| 223 | } | |||
| 224 | ||||
| 225 | memset(&props, 0, sizeof(props))__builtin_memset((&props), (0), (sizeof(props))); | |||
| 226 | props.max_brightness = RADEON_MAX_BL_LEVEL0xFF; | |||
| 227 | props.type = BACKLIGHT_RAW0; | |||
| 228 | snprintf(bl_name, sizeof(bl_name), | |||
| 229 | "radeon_bl%d", dev->primary->index); | |||
| 230 | bd = backlight_device_register(bl_name, drm_connector->kdev, | |||
| 231 | pdata, &radeon_atom_backlight_ops, &props); | |||
| 232 | if (IS_ERR(bd)) { | |||
| 233 | DRM_ERROR("Backlight registration failed\n")__drm_err("Backlight registration failed\n"); | |||
| 234 | goto error; | |||
| 235 | } | |||
| 236 | ||||
| 237 | pdata->encoder = radeon_encoder; | |||
| 238 | ||||
| 239 | dig = radeon_encoder->enc_priv; | |||
| 240 | dig->bl_dev = bd; | |||
| 241 | ||||
| 242 | bd->props.brightness = radeon_atom_backlight_get_brightness(bd); | |||
| 243 | /* Set a reasonable default here if the level is 0 otherwise | |||
| 244 | * fbdev will attempt to turn the backlight on after console | |||
| 245 | * unblanking and it will try and restore 0 which turns the backlight | |||
| 246 | * off again. | |||
| 247 | */ | |||
| 248 | if (bd->props.brightness == 0) | |||
| 249 | bd->props.brightness = RADEON_MAX_BL_LEVEL0xFF; | |||
| 250 | bd->props.power = FB_BLANK_UNBLANK0; | |||
| 251 | backlight_update_status(bd); | |||
| 252 | ||||
| 253 | DRM_INFO("radeon atom DIG backlight initialized\n")printk("\0016" "[" "drm" "] " "radeon atom DIG backlight initialized\n" ); | |||
| 254 | rdev->mode_info.bl_encoder = radeon_encoder; | |||
| 255 | ||||
| 256 | return; | |||
| 257 | ||||
| 258 | error: | |||
| 259 | kfree(pdata); | |||
| 260 | return; | |||
| 261 | } | |||
| 262 | ||||
| 263 | static void radeon_atom_backlight_exit(struct radeon_encoder *radeon_encoder) | |||
| 264 | { | |||
| 265 | struct drm_device *dev = radeon_encoder->base.dev; | |||
| 266 | struct radeon_device *rdev = dev->dev_private; | |||
| 267 | struct backlight_device *bd = NULL((void *)0); | |||
| 268 | struct radeon_encoder_atom_dig *dig; | |||
| 269 | ||||
| 270 | if (!radeon_encoder->enc_priv) | |||
| 271 | return; | |||
| 272 | ||||
| 273 | if (!rdev->is_atom_bios) | |||
| 274 | return; | |||
| 275 | ||||
| 276 | if (!(rdev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU0x0020)) | |||
| 277 | return; | |||
| 278 | ||||
| 279 | dig = radeon_encoder->enc_priv; | |||
| 280 | bd = dig->bl_dev; | |||
| 281 | dig->bl_dev = NULL((void *)0); | |||
| 282 | ||||
| 283 | if (bd) { | |||
| 284 | struct radeon_legacy_backlight_privdata *pdata; | |||
| 285 | ||||
| 286 | pdata = bl_get_data(bd); | |||
| 287 | backlight_device_unregister(bd); | |||
| 288 | kfree(pdata); | |||
| 289 | ||||
| 290 | DRM_INFO("radeon atom LVDS backlight unloaded\n")printk("\0016" "[" "drm" "] " "radeon atom LVDS backlight unloaded\n" ); | |||
| 291 | } | |||
| 292 | } | |||
| 293 | ||||
| 294 | static bool_Bool radeon_atom_mode_fixup(struct drm_encoder *encoder, | |||
| 295 | const struct drm_display_mode *mode, | |||
| 296 | struct drm_display_mode *adjusted_mode) | |||
| 297 | { | |||
| 298 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 299 | struct drm_device *dev = encoder->dev; | |||
| 300 | struct radeon_device *rdev = dev->dev_private; | |||
| 301 | ||||
| 302 | /* set the active encoder to connector routing */ | |||
| 303 | radeon_encoder_set_active_device(encoder); | |||
| 304 | drm_mode_set_crtcinfo(adjusted_mode, 0); | |||
| 305 | ||||
| 306 | /* hw bug */ | |||
| 307 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE(1<<4)) | |||
| 308 | && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) | |||
| 309 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; | |||
| 310 | ||||
| 311 | /* vertical FP must be at least 1 */ | |||
| 312 | if (mode->crtc_vsync_start == mode->crtc_vdisplay) | |||
| 313 | adjusted_mode->crtc_vsync_start++; | |||
| 314 | ||||
| 315 | /* get the native mode for scaling */ | |||
| 316 | if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 317 | radeon_panel_mode_fixup(encoder, adjusted_mode); | |||
| 318 | } else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) { | |||
| 319 | struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; | |||
| 320 | if (tv_dac) { | |||
| 321 | if (tv_dac->tv_std == TV_STD_NTSC || | |||
| 322 | tv_dac->tv_std == TV_STD_NTSC_J || | |||
| 323 | tv_dac->tv_std == TV_STD_PAL_M) | |||
| 324 | radeon_atom_get_tv_timings(rdev, 0, adjusted_mode); | |||
| 325 | else | |||
| 326 | radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); | |||
| 327 | } | |||
| 328 | } else if (radeon_encoder->rmx_type != RMX_OFF) { | |||
| 329 | radeon_panel_mode_fixup(encoder, adjusted_mode); | |||
| 330 | } | |||
| 331 | ||||
| 332 | if (ASIC_IS_DCE3(rdev)((rdev->family >= CHIP_RV620)) && | |||
| 333 | ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )) | ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) || | |||
| 334 | (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE0x00))) { | |||
| 335 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |||
| 336 | radeon_dp_set_link_config(connector, adjusted_mode); | |||
| 337 | } | |||
| 338 | ||||
| 339 | return true1; | |||
| 340 | } | |||
| 341 | ||||
| 342 | static void | |||
| 343 | atombios_dac_setup(struct drm_encoder *encoder, int action) | |||
| 344 | { | |||
| 345 | struct drm_device *dev = encoder->dev; | |||
| 346 | struct radeon_device *rdev = dev->dev_private; | |||
| 347 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 348 | DAC_ENCODER_CONTROL_PS_ALLOCATIONDAC_ENCODER_CONTROL_PARAMETERS args; | |||
| 349 | int index = 0; | |||
| 350 | struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; | |||
| 351 | ||||
| 352 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 353 | ||||
| 354 | switch (radeon_encoder->encoder_id) { | |||
| 355 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 356 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 357 | index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DAC1EncoderControl )/sizeof(USHORT)); | |||
| 358 | break; | |||
| 359 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 360 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 361 | index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DAC2EncoderControl )/sizeof(USHORT)); | |||
| 362 | break; | |||
| 363 | } | |||
| 364 | ||||
| 365 | args.ucAction = action; | |||
| 366 | ||||
| 367 | if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT((0x1L << 0x00000000 ) | (0x1L << 0x00000004 )))) | |||
| 368 | args.ucDacStandard = ATOM_DAC1_PS21; | |||
| 369 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 370 | args.ucDacStandard = ATOM_DAC1_CV2; | |||
| 371 | else { | |||
| 372 | switch (dac_info->tv_std) { | |||
| 373 | case TV_STD_PAL: | |||
| 374 | case TV_STD_PAL_M: | |||
| 375 | case TV_STD_SCART_PAL: | |||
| 376 | case TV_STD_SECAM: | |||
| 377 | case TV_STD_PAL_CN: | |||
| 378 | args.ucDacStandard = ATOM_DAC1_PAL4; | |||
| 379 | break; | |||
| 380 | case TV_STD_NTSC: | |||
| 381 | case TV_STD_NTSC_J: | |||
| 382 | case TV_STD_PAL_60: | |||
| 383 | default: | |||
| 384 | args.ucDacStandard = ATOM_DAC1_NTSC3; | |||
| 385 | break; | |||
| 386 | } | |||
| 387 | } | |||
| 388 | args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 389 | ||||
| 390 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 391 | ||||
| 392 | } | |||
| 393 | ||||
| 394 | static void | |||
| 395 | atombios_tv_setup(struct drm_encoder *encoder, int action) | |||
| 396 | { | |||
| 397 | struct drm_device *dev = encoder->dev; | |||
| 398 | struct radeon_device *rdev = dev->dev_private; | |||
| 399 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 400 | TV_ENCODER_CONTROL_PS_ALLOCATION args; | |||
| 401 | int index = 0; | |||
| 402 | struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; | |||
| 403 | ||||
| 404 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 405 | ||||
| 406 | index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, TVEncoderControl )/sizeof(USHORT)); | |||
| 407 | ||||
| 408 | args.sTVEncoder.ucAction = action; | |||
| 409 | ||||
| 410 | if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 411 | args.sTVEncoder.ucTvStandard = ATOM_TV_CV16; | |||
| 412 | else { | |||
| 413 | switch (dac_info->tv_std) { | |||
| 414 | case TV_STD_NTSC: | |||
| 415 | args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC1; | |||
| 416 | break; | |||
| 417 | case TV_STD_PAL: | |||
| 418 | args.sTVEncoder.ucTvStandard = ATOM_TV_PAL3; | |||
| 419 | break; | |||
| 420 | case TV_STD_PAL_M: | |||
| 421 | args.sTVEncoder.ucTvStandard = ATOM_TV_PALM4; | |||
| 422 | break; | |||
| 423 | case TV_STD_PAL_60: | |||
| 424 | args.sTVEncoder.ucTvStandard = ATOM_TV_PAL607; | |||
| 425 | break; | |||
| 426 | case TV_STD_NTSC_J: | |||
| 427 | args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ2; | |||
| 428 | break; | |||
| 429 | case TV_STD_SCART_PAL: | |||
| 430 | args.sTVEncoder.ucTvStandard = ATOM_TV_PAL3; /* ??? */ | |||
| 431 | break; | |||
| 432 | case TV_STD_SECAM: | |||
| 433 | args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM8; | |||
| 434 | break; | |||
| 435 | case TV_STD_PAL_CN: | |||
| 436 | args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN5; | |||
| 437 | break; | |||
| 438 | default: | |||
| 439 | args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC1; | |||
| 440 | break; | |||
| 441 | } | |||
| 442 | } | |||
| 443 | ||||
| 444 | args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 445 | ||||
| 446 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 447 | ||||
| 448 | } | |||
| 449 | ||||
| 450 | static u8 radeon_atom_get_bpc(struct drm_encoder *encoder) | |||
| 451 | { | |||
| 452 | int bpc = 8; | |||
| 453 | ||||
| 454 | if (encoder->crtc) { | |||
| 455 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc)({ const __typeof( ((struct radeon_crtc *)0)->base ) *__mptr = (encoder->crtc); (struct radeon_crtc *)( (char *)__mptr - __builtin_offsetof(struct radeon_crtc, base) );}); | |||
| 456 | bpc = radeon_crtc->bpc; | |||
| 457 | } | |||
| 458 | ||||
| 459 | switch (bpc) { | |||
| 460 | case 0: | |||
| 461 | return PANEL_BPC_UNDEFINE0x00; | |||
| 462 | case 6: | |||
| 463 | return PANEL_6BIT_PER_COLOR0x01; | |||
| 464 | case 8: | |||
| 465 | default: | |||
| 466 | return PANEL_8BIT_PER_COLOR0x02; | |||
| 467 | case 10: | |||
| 468 | return PANEL_10BIT_PER_COLOR0x03; | |||
| 469 | case 12: | |||
| 470 | return PANEL_12BIT_PER_COLOR0x04; | |||
| 471 | case 16: | |||
| 472 | return PANEL_16BIT_PER_COLOR0x05; | |||
| 473 | } | |||
| 474 | } | |||
| 475 | ||||
| 476 | union dvo_encoder_control { | |||
| 477 | ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION ext_tmds; | |||
| 478 | DVO_ENCODER_CONTROL_PS_ALLOCATION dvo; | |||
| 479 | DVO_ENCODER_CONTROL_PS_ALLOCATION_V3DVO_ENCODER_CONTROL_PARAMETERS_V3 dvo_v3; | |||
| 480 | DVO_ENCODER_CONTROL_PS_ALLOCATION_V1_4DVO_ENCODER_CONTROL_PARAMETERS_V1_4 dvo_v4; | |||
| 481 | }; | |||
| 482 | ||||
| 483 | void | |||
| 484 | atombios_dvo_setup(struct drm_encoder *encoder, int action) | |||
| 485 | { | |||
| 486 | struct drm_device *dev = encoder->dev; | |||
| 487 | struct radeon_device *rdev = dev->dev_private; | |||
| 488 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 489 | union dvo_encoder_control args; | |||
| 490 | int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DVOEncoderControl )/sizeof(USHORT)); | |||
| 491 | uint8_t frev, crev; | |||
| 492 | ||||
| 493 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 494 | ||||
| 495 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 496 | return; | |||
| 497 | ||||
| 498 | /* some R4xx chips have the wrong frev */ | |||
| 499 | if (rdev->family <= CHIP_RV410) | |||
| 500 | frev = 1; | |||
| 501 | ||||
| 502 | switch (frev) { | |||
| 503 | case 1: | |||
| 504 | switch (crev) { | |||
| 505 | case 1: | |||
| 506 | /* R4xx, R5xx */ | |||
| 507 | args.ext_tmds.sXTmdsEncoder.ucEnable = action; | |||
| 508 | ||||
| 509 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 510 | args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL0x01; | |||
| 511 | ||||
| 512 | args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB0x00000002; | |||
| 513 | break; | |||
| 514 | case 2: | |||
| 515 | /* RS600/690/740 */ | |||
| 516 | args.dvo.sDVOEncoder.ucAction = action; | |||
| 517 | args.dvo.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 518 | /* DFP1, CRT1, TV1 depending on the type of port */ | |||
| 519 | args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX0x00000003; | |||
| 520 | ||||
| 521 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 522 | args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL0x01; | |||
| 523 | break; | |||
| 524 | case 3: | |||
| 525 | /* R6xx */ | |||
| 526 | args.dvo_v3.ucAction = action; | |||
| 527 | args.dvo_v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 528 | args.dvo_v3.ucDVOConfig = 0; /* XXX */ | |||
| 529 | break; | |||
| 530 | case 4: | |||
| 531 | /* DCE8 */ | |||
| 532 | args.dvo_v4.ucAction = action; | |||
| 533 | args.dvo_v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 534 | args.dvo_v4.ucDVOConfig = 0; /* XXX */ | |||
| 535 | args.dvo_v4.ucBitPerColor = radeon_atom_get_bpc(encoder); | |||
| 536 | break; | |||
| 537 | default: | |||
| 538 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 539 | break; | |||
| 540 | } | |||
| 541 | break; | |||
| 542 | default: | |||
| 543 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 544 | break; | |||
| 545 | } | |||
| 546 | ||||
| 547 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 548 | } | |||
| 549 | ||||
| 550 | union lvds_encoder_control { | |||
| 551 | LVDS_ENCODER_CONTROL_PS_ALLOCATIONLVDS_ENCODER_CONTROL_PARAMETERS v1; | |||
| 552 | LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2LVDS_ENCODER_CONTROL_PARAMETERS_V2 v2; | |||
| 553 | }; | |||
| 554 | ||||
| 555 | void | |||
| 556 | atombios_digital_setup(struct drm_encoder *encoder, int action) | |||
| 557 | { | |||
| 558 | struct drm_device *dev = encoder->dev; | |||
| 559 | struct radeon_device *rdev = dev->dev_private; | |||
| 560 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 561 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 562 | union lvds_encoder_control args; | |||
| 563 | int index = 0; | |||
| 564 | int hdmi_detected = 0; | |||
| 565 | uint8_t frev, crev; | |||
| 566 | ||||
| 567 | if (!dig) | |||
| 568 | return; | |||
| 569 | ||||
| 570 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI3) | |||
| 571 | hdmi_detected = 1; | |||
| 572 | ||||
| 573 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 574 | ||||
| 575 | switch (radeon_encoder->encoder_id) { | |||
| 576 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 577 | index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, MC_SEQ_Control )/sizeof(USHORT)); | |||
| 578 | break; | |||
| 579 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 580 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 581 | index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, PatchMCSetting )/sizeof(USHORT)); | |||
| 582 | break; | |||
| 583 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 584 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) | |||
| 585 | index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, MC_SEQ_Control )/sizeof(USHORT)); | |||
| 586 | else | |||
| 587 | index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, LVTMAEncoderControl )/sizeof(USHORT)); | |||
| 588 | break; | |||
| 589 | } | |||
| 590 | ||||
| 591 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 592 | return; | |||
| 593 | ||||
| 594 | switch (frev) { | |||
| 595 | case 1: | |||
| 596 | case 2: | |||
| 597 | switch (crev) { | |||
| 598 | case 1: | |||
| 599 | args.v1.ucMisc = 0; | |||
| 600 | args.v1.ucAction = action; | |||
| 601 | if (hdmi_detected) | |||
| 602 | args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE0x08; | |||
| 603 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 604 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 605 | if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL0x00000001) | |||
| 606 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL0x01; | |||
| 607 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB0x00000002) | |||
| 608 | args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB0x00000002; | |||
| 609 | } else { | |||
| 610 | if (dig->linkb) | |||
| 611 | args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB0x04; | |||
| 612 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 613 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL0x01; | |||
| 614 | /*if (pScrn->rgbBits == 8) */ | |||
| 615 | args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB0x00000002; | |||
| 616 | } | |||
| 617 | break; | |||
| 618 | case 2: | |||
| 619 | case 3: | |||
| 620 | args.v2.ucMisc = 0; | |||
| 621 | args.v2.ucAction = action; | |||
| 622 | if (crev == 3) { | |||
| 623 | if (dig->coherent_mode) | |||
| 624 | args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT0x02; | |||
| 625 | } | |||
| 626 | if (hdmi_detected) | |||
| 627 | args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE0x08; | |||
| 628 | args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 629 | args.v2.ucTruncate = 0; | |||
| 630 | args.v2.ucSpatial = 0; | |||
| 631 | args.v2.ucTemporal = 0; | |||
| 632 | args.v2.ucFRC = 0; | |||
| 633 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 634 | if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL0x00000001) | |||
| 635 | args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL0x01; | |||
| 636 | if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL0x00000020) { | |||
| 637 | args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN0x01; | |||
| 638 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB0x00000002) | |||
| 639 | args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH0x10; | |||
| 640 | } | |||
| 641 | if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL0x00000040) { | |||
| 642 | args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN0x01; | |||
| 643 | if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB0x00000002) | |||
| 644 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH0x10; | |||
| 645 | if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT2) & 0x3) == 2) | |||
| 646 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_40x20; | |||
| 647 | } | |||
| 648 | } else { | |||
| 649 | if (dig->linkb) | |||
| 650 | args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB0x04; | |||
| 651 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 652 | args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL0x01; | |||
| 653 | } | |||
| 654 | break; | |||
| 655 | default: | |||
| 656 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 657 | break; | |||
| 658 | } | |||
| 659 | break; | |||
| 660 | default: | |||
| 661 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 662 | break; | |||
| 663 | } | |||
| 664 | ||||
| 665 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 666 | } | |||
| 667 | ||||
| 668 | int | |||
| 669 | atombios_get_encoder_mode(struct drm_encoder *encoder) | |||
| 670 | { | |||
| 671 | struct drm_device *dev = encoder->dev; | |||
| 672 | struct radeon_device *rdev = dev->dev_private; | |||
| 673 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 674 | struct drm_connector *connector; | |||
| 675 | struct radeon_connector *radeon_connector; | |||
| 676 | struct radeon_connector_atom_dig *dig_connector; | |||
| 677 | ||||
| 678 | /* dp bridges are always DP */ | |||
| 679 | if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE0x00) | |||
| 680 | return ATOM_ENCODER_MODE_DP0; | |||
| 681 | ||||
| 682 | /* DVO is always DVO */ | |||
| 683 | if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DVO10x0B) || | |||
| 684 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14)) | |||
| 685 | return ATOM_ENCODER_MODE_DVO16; | |||
| 686 | ||||
| 687 | connector = radeon_get_connector_for_encoder(encoder); | |||
| 688 | /* if we don't have an active device yet, just use one of | |||
| 689 | * the connectors tied to the encoder. | |||
| 690 | */ | |||
| 691 | if (!connector) | |||
| 692 | connector = radeon_get_connector_for_encoder_init(encoder); | |||
| 693 | radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 694 | ||||
| 695 | switch (connector->connector_type) { | |||
| 696 | case DRM_MODE_CONNECTOR_DVII2: | |||
| 697 | case DRM_MODE_CONNECTOR_HDMIB12: /* HDMI-B is basically DL-DVI; analog works fine */ | |||
| 698 | if (radeon_audio != 0) { | |||
| 699 | if (radeon_connector->use_digital && | |||
| 700 | (radeon_connector->audio == RADEON_AUDIO_ENABLE)) | |||
| 701 | return ATOM_ENCODER_MODE_HDMI3; | |||
| 702 | else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && | |||
| 703 | (radeon_connector->audio == RADEON_AUDIO_AUTO)) | |||
| 704 | return ATOM_ENCODER_MODE_HDMI3; | |||
| 705 | else if (radeon_connector->use_digital) | |||
| 706 | return ATOM_ENCODER_MODE_DVI2; | |||
| 707 | else | |||
| 708 | return ATOM_ENCODER_MODE_CRT15; | |||
| 709 | } else if (radeon_connector->use_digital) { | |||
| 710 | return ATOM_ENCODER_MODE_DVI2; | |||
| 711 | } else { | |||
| 712 | return ATOM_ENCODER_MODE_CRT15; | |||
| 713 | } | |||
| 714 | break; | |||
| 715 | case DRM_MODE_CONNECTOR_DVID3: | |||
| 716 | case DRM_MODE_CONNECTOR_HDMIA11: | |||
| 717 | default: | |||
| 718 | if (radeon_audio != 0) { | |||
| 719 | if (radeon_connector->audio == RADEON_AUDIO_ENABLE) | |||
| 720 | return ATOM_ENCODER_MODE_HDMI3; | |||
| 721 | else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && | |||
| 722 | (radeon_connector->audio == RADEON_AUDIO_AUTO)) | |||
| 723 | return ATOM_ENCODER_MODE_HDMI3; | |||
| 724 | else | |||
| 725 | return ATOM_ENCODER_MODE_DVI2; | |||
| 726 | } else { | |||
| 727 | return ATOM_ENCODER_MODE_DVI2; | |||
| 728 | } | |||
| 729 | break; | |||
| 730 | case DRM_MODE_CONNECTOR_LVDS7: | |||
| 731 | return ATOM_ENCODER_MODE_LVDS1; | |||
| 732 | break; | |||
| 733 | case DRM_MODE_CONNECTOR_DisplayPort10: | |||
| 734 | dig_connector = radeon_connector->con_priv; | |||
| 735 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT0x13) || | |||
| 736 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP0x14)) { | |||
| 737 | if (radeon_audio != 0 && | |||
| 738 | drm_detect_monitor_audio(radeon_connector_edid(connector)) && | |||
| 739 | ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR)) && !ASIC_IS_DCE5(rdev)((rdev->family >= CHIP_BARTS))) | |||
| 740 | return ATOM_ENCODER_MODE_DP_AUDIO5; | |||
| 741 | return ATOM_ENCODER_MODE_DP0; | |||
| 742 | } else if (radeon_audio != 0) { | |||
| 743 | if (radeon_connector->audio == RADEON_AUDIO_ENABLE) | |||
| 744 | return ATOM_ENCODER_MODE_HDMI3; | |||
| 745 | else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) && | |||
| 746 | (radeon_connector->audio == RADEON_AUDIO_AUTO)) | |||
| 747 | return ATOM_ENCODER_MODE_HDMI3; | |||
| 748 | else | |||
| 749 | return ATOM_ENCODER_MODE_DVI2; | |||
| 750 | } else { | |||
| 751 | return ATOM_ENCODER_MODE_DVI2; | |||
| 752 | } | |||
| 753 | break; | |||
| 754 | case DRM_MODE_CONNECTOR_eDP14: | |||
| 755 | if (radeon_audio != 0 && | |||
| 756 | drm_detect_monitor_audio(radeon_connector_edid(connector)) && | |||
| 757 | ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR)) && !ASIC_IS_DCE5(rdev)((rdev->family >= CHIP_BARTS))) | |||
| 758 | return ATOM_ENCODER_MODE_DP_AUDIO5; | |||
| 759 | return ATOM_ENCODER_MODE_DP0; | |||
| 760 | case DRM_MODE_CONNECTOR_DVIA4: | |||
| 761 | case DRM_MODE_CONNECTOR_VGA1: | |||
| 762 | return ATOM_ENCODER_MODE_CRT15; | |||
| 763 | break; | |||
| 764 | case DRM_MODE_CONNECTOR_Composite5: | |||
| 765 | case DRM_MODE_CONNECTOR_SVIDEO6: | |||
| 766 | case DRM_MODE_CONNECTOR_9PinDIN9: | |||
| 767 | /* fix me */ | |||
| 768 | return ATOM_ENCODER_MODE_TV13; | |||
| 769 | /*return ATOM_ENCODER_MODE_CV;*/ | |||
| 770 | break; | |||
| 771 | } | |||
| 772 | } | |||
| 773 | ||||
| 774 | /* | |||
| 775 | * DIG Encoder/Transmitter Setup | |||
| 776 | * | |||
| 777 | * DCE 3.0/3.1 | |||
| 778 | * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. | |||
| 779 | * Supports up to 3 digital outputs | |||
| 780 | * - 2 DIG encoder blocks. | |||
| 781 | * DIG1 can drive UNIPHY link A or link B | |||
| 782 | * DIG2 can drive UNIPHY link B or LVTMA | |||
| 783 | * | |||
| 784 | * DCE 3.2 | |||
| 785 | * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). | |||
| 786 | * Supports up to 5 digital outputs | |||
| 787 | * - 2 DIG encoder blocks. | |||
| 788 | * DIG1/2 can drive UNIPHY0/1/2 link A or link B | |||
| 789 | * | |||
| 790 | * DCE 4.0/5.0/6.0 | |||
| 791 | * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). | |||
| 792 | * Supports up to 6 digital outputs | |||
| 793 | * - 6 DIG encoder blocks. | |||
| 794 | * - DIG to PHY mapping is hardcoded | |||
| 795 | * DIG1 drives UNIPHY0 link A, A+B | |||
| 796 | * DIG2 drives UNIPHY0 link B | |||
| 797 | * DIG3 drives UNIPHY1 link A, A+B | |||
| 798 | * DIG4 drives UNIPHY1 link B | |||
| 799 | * DIG5 drives UNIPHY2 link A, A+B | |||
| 800 | * DIG6 drives UNIPHY2 link B | |||
| 801 | * | |||
| 802 | * DCE 4.1 | |||
| 803 | * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). | |||
| 804 | * Supports up to 6 digital outputs | |||
| 805 | * - 2 DIG encoder blocks. | |||
| 806 | * llano | |||
| 807 | * DIG1/2 can drive UNIPHY0/1/2 link A or link B | |||
| 808 | * ontario | |||
| 809 | * DIG1 drives UNIPHY0/1/2 link A | |||
| 810 | * DIG2 drives UNIPHY0/1/2 link B | |||
| 811 | * | |||
| 812 | * Routing | |||
| 813 | * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) | |||
| 814 | * Examples: | |||
| 815 | * crtc0 -> dig2 -> LVTMA links A+B -> TMDS/HDMI | |||
| 816 | * crtc1 -> dig1 -> UNIPHY0 link B -> DP | |||
| 817 | * crtc0 -> dig1 -> UNIPHY2 link A -> LVDS | |||
| 818 | * crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI | |||
| 819 | */ | |||
| 820 | ||||
| 821 | union dig_encoder_control { | |||
| 822 | DIG_ENCODER_CONTROL_PS_ALLOCATIONDIG_ENCODER_CONTROL_PARAMETERS v1; | |||
| 823 | DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; | |||
| 824 | DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; | |||
| 825 | DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; | |||
| 826 | }; | |||
| 827 | ||||
| 828 | void | |||
| 829 | atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override) | |||
| 830 | { | |||
| 831 | struct drm_device *dev = encoder->dev; | |||
| 832 | struct radeon_device *rdev = dev->dev_private; | |||
| 833 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 834 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 835 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |||
| 836 | union dig_encoder_control args; | |||
| 837 | int index = 0; | |||
| 838 | uint8_t frev, crev; | |||
| 839 | int dp_clock = 0; | |||
| 840 | int dp_lane_count = 0; | |||
| 841 | int hpd_id = RADEON_HPD_NONE; | |||
| 842 | ||||
| 843 | if (connector) { | |||
| 844 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 845 | struct radeon_connector_atom_dig *dig_connector = | |||
| 846 | radeon_connector->con_priv; | |||
| 847 | ||||
| 848 | dp_clock = dig_connector->dp_clock; | |||
| 849 | dp_lane_count = dig_connector->dp_lane_count; | |||
| 850 | hpd_id = radeon_connector->hpd.hpd; | |||
| 851 | } | |||
| 852 | ||||
| 853 | /* no dig encoder assigned */ | |||
| 854 | if (dig->dig_encoder == -1) | |||
| 855 | return; | |||
| 856 | ||||
| 857 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 858 | ||||
| 859 | if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) | |||
| 860 | index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DIGxEncoderControl )/sizeof(USHORT)); | |||
| 861 | else { | |||
| 862 | if (dig->dig_encoder) | |||
| 863 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DIG2EncoderControl )/sizeof(USHORT)); | |||
| 864 | else | |||
| 865 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DIG1EncoderControl )/sizeof(USHORT)); | |||
| 866 | } | |||
| 867 | ||||
| 868 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 869 | return; | |||
| 870 | ||||
| 871 | switch (frev) { | |||
| 872 | case 1: | |||
| 873 | switch (crev) { | |||
| 874 | case 1: | |||
| 875 | args.v1.ucAction = action; | |||
| 876 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 877 | if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE0x10) | |||
| 878 | args.v3.ucPanelMode = panel_mode; | |||
| 879 | else | |||
| 880 | args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); | |||
| 881 | ||||
| 882 | if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)(((args.v1.ucEncoderMode) == 0) || ((args.v1.ucEncoderMode) == 5))) | |||
| 883 | args.v1.ucLaneNum = dp_lane_count; | |||
| 884 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 885 | args.v1.ucLaneNum = 8; | |||
| 886 | else | |||
| 887 | args.v1.ucLaneNum = 4; | |||
| 888 | ||||
| 889 | switch (radeon_encoder->encoder_id) { | |||
| 890 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 891 | args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER10x00; | |||
| 892 | break; | |||
| 893 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 894 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 895 | args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER20x08; | |||
| 896 | break; | |||
| 897 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 898 | args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER30x10; | |||
| 899 | break; | |||
| 900 | } | |||
| 901 | if (dig->linkb) | |||
| 902 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB0x04; | |||
| 903 | else | |||
| 904 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA0x00; | |||
| 905 | ||||
| 906 | if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)(((args.v1.ucEncoderMode) == 0) || ((args.v1.ucEncoderMode) == 5)) && (dp_clock == 270000)) | |||
| 907 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ0x01; | |||
| 908 | ||||
| 909 | break; | |||
| 910 | case 2: | |||
| 911 | case 3: | |||
| 912 | args.v3.ucAction = action; | |||
| 913 | args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 914 | if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE0x10) | |||
| 915 | args.v3.ucPanelMode = panel_mode; | |||
| 916 | else | |||
| 917 | args.v3.ucEncoderMode = atombios_get_encoder_mode(encoder); | |||
| 918 | ||||
| 919 | if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode)(((args.v3.ucEncoderMode) == 0) || ((args.v3.ucEncoderMode) == 5))) | |||
| 920 | args.v3.ucLaneNum = dp_lane_count; | |||
| 921 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 922 | args.v3.ucLaneNum = 8; | |||
| 923 | else | |||
| 924 | args.v3.ucLaneNum = 4; | |||
| 925 | ||||
| 926 | if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode)(((args.v3.ucEncoderMode) == 0) || ((args.v3.ucEncoderMode) == 5)) && (dp_clock == 270000)) | |||
| 927 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ0x01; | |||
| 928 | if (enc_override != -1) | |||
| 929 | args.v3.acConfig.ucDigSel = enc_override; | |||
| 930 | else | |||
| 931 | args.v3.acConfig.ucDigSel = dig->dig_encoder; | |||
| 932 | args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder); | |||
| 933 | break; | |||
| 934 | case 4: | |||
| 935 | args.v4.ucAction = action; | |||
| 936 | args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 937 | if (action == ATOM_ENCODER_CMD_SETUP_PANEL_MODE0x10) | |||
| 938 | args.v4.ucPanelMode = panel_mode; | |||
| 939 | else | |||
| 940 | args.v4.ucEncoderMode = atombios_get_encoder_mode(encoder); | |||
| 941 | ||||
| 942 | if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)(((args.v4.ucEncoderMode) == 0) || ((args.v4.ucEncoderMode) == 5))) | |||
| 943 | args.v4.ucLaneNum = dp_lane_count; | |||
| 944 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 945 | args.v4.ucLaneNum = 8; | |||
| 946 | else | |||
| 947 | args.v4.ucLaneNum = 4; | |||
| 948 | ||||
| 949 | if (ENCODER_MODE_IS_DP(args.v4.ucEncoderMode)(((args.v4.ucEncoderMode) == 0) || ((args.v4.ucEncoderMode) == 5))) { | |||
| 950 | if (dp_clock == 540000) | |||
| 951 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ0x02; | |||
| 952 | else if (dp_clock == 324000) | |||
| 953 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_3_24GHZ0x03; | |||
| 954 | else if (dp_clock == 270000) | |||
| 955 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ0x01; | |||
| 956 | else | |||
| 957 | args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ0x00; | |||
| 958 | } | |||
| 959 | ||||
| 960 | if (enc_override != -1) | |||
| 961 | args.v4.acConfig.ucDigSel = enc_override; | |||
| 962 | else | |||
| 963 | args.v4.acConfig.ucDigSel = dig->dig_encoder; | |||
| 964 | args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder); | |||
| 965 | if (hpd_id == RADEON_HPD_NONE) | |||
| 966 | args.v4.ucHPD_ID = 0; | |||
| 967 | else | |||
| 968 | args.v4.ucHPD_ID = hpd_id + 1; | |||
| 969 | break; | |||
| 970 | default: | |||
| 971 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 972 | break; | |||
| 973 | } | |||
| 974 | break; | |||
| 975 | default: | |||
| 976 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 977 | break; | |||
| 978 | } | |||
| 979 | ||||
| 980 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 981 | ||||
| 982 | } | |||
| 983 | ||||
| 984 | void | |||
| 985 | atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode) | |||
| 986 | { | |||
| 987 | atombios_dig_encoder_setup2(encoder, action, panel_mode, -1); | |||
| 988 | } | |||
| 989 | ||||
| 990 | union dig_transmitter_control { | |||
| 991 | DIG_TRANSMITTER_CONTROL_PS_ALLOCATIONDIG_TRANSMITTER_CONTROL_PARAMETERS v1; | |||
| 992 | DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; | |||
| 993 | DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; | |||
| 994 | DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; | |||
| 995 | DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5; | |||
| 996 | }; | |||
| 997 | ||||
| 998 | void | |||
| 999 | atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe) | |||
| 1000 | { | |||
| 1001 | struct drm_device *dev = encoder->dev; | |||
| 1002 | struct radeon_device *rdev = dev->dev_private; | |||
| 1003 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1004 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 1005 | struct drm_connector *connector; | |||
| 1006 | union dig_transmitter_control args; | |||
| 1007 | int index = 0; | |||
| 1008 | uint8_t frev, crev; | |||
| 1009 | bool_Bool is_dp = false0; | |||
| 1010 | int pll_id = 0; | |||
| 1011 | int dp_clock = 0; | |||
| 1012 | int dp_lane_count = 0; | |||
| 1013 | int connector_object_id = 0; | |||
| 1014 | int igp_lane_info = 0; | |||
| 1015 | int dig_encoder = dig->dig_encoder; | |||
| 1016 | int hpd_id = RADEON_HPD_NONE; | |||
| 1017 | ||||
| 1018 | if (action == ATOM_TRANSMITTER_ACTION_INIT7) { | |||
| 1019 | connector = radeon_get_connector_for_encoder_init(encoder); | |||
| 1020 | /* just needed to avoid bailing in the encoder check. the encoder | |||
| 1021 | * isn't used for init | |||
| 1022 | */ | |||
| 1023 | dig_encoder = 0; | |||
| 1024 | } else | |||
| 1025 | connector = radeon_get_connector_for_encoder(encoder); | |||
| 1026 | ||||
| 1027 | if (connector) { | |||
| 1028 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 1029 | struct radeon_connector_atom_dig *dig_connector = | |||
| 1030 | radeon_connector->con_priv; | |||
| 1031 | ||||
| 1032 | hpd_id = radeon_connector->hpd.hpd; | |||
| 1033 | dp_clock = dig_connector->dp_clock; | |||
| 1034 | dp_lane_count = dig_connector->dp_lane_count; | |||
| 1035 | connector_object_id = | |||
| 1036 | (radeon_connector->connector_object_id & OBJECT_ID_MASK0x00FF) >> OBJECT_ID_SHIFT0x00; | |||
| 1037 | igp_lane_info = dig_connector->igp_lane_info; | |||
| 1038 | } | |||
| 1039 | ||||
| 1040 | if (encoder->crtc) { | |||
| 1041 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc)({ const __typeof( ((struct radeon_crtc *)0)->base ) *__mptr = (encoder->crtc); (struct radeon_crtc *)( (char *)__mptr - __builtin_offsetof(struct radeon_crtc, base) );}); | |||
| 1042 | pll_id = radeon_crtc->pll_id; | |||
| 1043 | } | |||
| 1044 | ||||
| 1045 | /* no dig encoder assigned */ | |||
| 1046 | if (dig_encoder == -1) | |||
| 1047 | return; | |||
| 1048 | ||||
| 1049 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))(((atombios_get_encoder_mode(encoder)) == 0) || ((atombios_get_encoder_mode (encoder)) == 5))) | |||
| 1050 | is_dp = true1; | |||
| 1051 | ||||
| 1052 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 1053 | ||||
| 1054 | switch (radeon_encoder->encoder_id) { | |||
| 1055 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 1056 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DVOOutputControl )/sizeof(USHORT)); | |||
| 1057 | break; | |||
| 1058 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1059 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1060 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1061 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 1062 | index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DIG1TransmitterControl )/sizeof(USHORT)); | |||
| 1063 | break; | |||
| 1064 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 1065 | index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DIG2TransmitterControl )/sizeof(USHORT)); | |||
| 1066 | break; | |||
| 1067 | } | |||
| 1068 | ||||
| 1069 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 1070 | return; | |||
| 1071 | ||||
| 1072 | switch (frev) { | |||
| 1073 | case 1: | |||
| 1074 | switch (crev) { | |||
| 1075 | case 1: | |||
| 1076 | args.v1.ucAction = action; | |||
| 1077 | if (action == ATOM_TRANSMITTER_ACTION_INIT7) { | |||
| 1078 | args.v1.usInitInfo = cpu_to_le16(connector_object_id)((__uint16_t)(connector_object_id)); | |||
| 1079 | } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH11) { | |||
| 1080 | args.v1.asMode.ucLaneSel = lane_num; | |||
| 1081 | args.v1.asMode.ucLaneSet = lane_set; | |||
| 1082 | } else { | |||
| 1083 | if (is_dp) | |||
| 1084 | args.v1.usPixelClock = cpu_to_le16(dp_clock / 10)((__uint16_t)(dp_clock / 10)); | |||
| 1085 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1086 | args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10)((__uint16_t)((radeon_encoder->pixel_clock / 2) / 10)); | |||
| 1087 | else | |||
| 1088 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1089 | } | |||
| 1090 | ||||
| 1091 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL0x00; | |||
| 1092 | ||||
| 1093 | if (dig_encoder) | |||
| 1094 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER0x08; | |||
| 1095 | else | |||
| 1096 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER0x00; | |||
| 1097 | ||||
| 1098 | if ((rdev->flags & RADEON_IS_IGP) && | |||
| 1099 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E)) { | |||
| 1100 | if (is_dp || | |||
| 1101 | !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) { | |||
| 1102 | if (igp_lane_info & 0x1) | |||
| 1103 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_30x00; | |||
| 1104 | else if (igp_lane_info & 0x2) | |||
| 1105 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_70x40; | |||
| 1106 | else if (igp_lane_info & 0x4) | |||
| 1107 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_110x80; | |||
| 1108 | else if (igp_lane_info & 0x8) | |||
| 1109 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_150xc0; | |||
| 1110 | } else { | |||
| 1111 | if (igp_lane_info & 0x3) | |||
| 1112 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_70x00; | |||
| 1113 | else if (igp_lane_info & 0xc) | |||
| 1114 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_150x80; | |||
| 1115 | } | |||
| 1116 | } | |||
| 1117 | ||||
| 1118 | if (dig->linkb) | |||
| 1119 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB0x04; | |||
| 1120 | else | |||
| 1121 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA0x00; | |||
| 1122 | ||||
| 1123 | if (is_dp) | |||
| 1124 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT0x02; | |||
| 1125 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )))) { | |||
| 1126 | if (dig->coherent_mode) | |||
| 1127 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT0x02; | |||
| 1128 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1129 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK0x01; | |||
| 1130 | } | |||
| 1131 | break; | |||
| 1132 | case 2: | |||
| 1133 | args.v2.ucAction = action; | |||
| 1134 | if (action == ATOM_TRANSMITTER_ACTION_INIT7) { | |||
| 1135 | args.v2.usInitInfo = cpu_to_le16(connector_object_id)((__uint16_t)(connector_object_id)); | |||
| 1136 | } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH11) { | |||
| 1137 | args.v2.asMode.ucLaneSel = lane_num; | |||
| 1138 | args.v2.asMode.ucLaneSet = lane_set; | |||
| 1139 | } else { | |||
| 1140 | if (is_dp) | |||
| 1141 | args.v2.usPixelClock = cpu_to_le16(dp_clock / 10)((__uint16_t)(dp_clock / 10)); | |||
| 1142 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1143 | args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10)((__uint16_t)((radeon_encoder->pixel_clock / 2) / 10)); | |||
| 1144 | else | |||
| 1145 | args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1146 | } | |||
| 1147 | ||||
| 1148 | args.v2.acConfig.ucEncoderSel = dig_encoder; | |||
| 1149 | if (dig->linkb) | |||
| 1150 | args.v2.acConfig.ucLinkSel = 1; | |||
| 1151 | ||||
| 1152 | switch (radeon_encoder->encoder_id) { | |||
| 1153 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1154 | args.v2.acConfig.ucTransmitterSel = 0; | |||
| 1155 | break; | |||
| 1156 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1157 | args.v2.acConfig.ucTransmitterSel = 1; | |||
| 1158 | break; | |||
| 1159 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1160 | args.v2.acConfig.ucTransmitterSel = 2; | |||
| 1161 | break; | |||
| 1162 | } | |||
| 1163 | ||||
| 1164 | if (is_dp) { | |||
| 1165 | args.v2.acConfig.fCoherentMode = 1; | |||
| 1166 | args.v2.acConfig.fDPConnector = 1; | |||
| 1167 | } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )))) { | |||
| 1168 | if (dig->coherent_mode) | |||
| 1169 | args.v2.acConfig.fCoherentMode = 1; | |||
| 1170 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1171 | args.v2.acConfig.fDualLinkConnector = 1; | |||
| 1172 | } | |||
| 1173 | break; | |||
| 1174 | case 3: | |||
| 1175 | args.v3.ucAction = action; | |||
| 1176 | if (action == ATOM_TRANSMITTER_ACTION_INIT7) { | |||
| 1177 | args.v3.usInitInfo = cpu_to_le16(connector_object_id)((__uint16_t)(connector_object_id)); | |||
| 1178 | } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH11) { | |||
| 1179 | args.v3.asMode.ucLaneSel = lane_num; | |||
| 1180 | args.v3.asMode.ucLaneSet = lane_set; | |||
| 1181 | } else { | |||
| 1182 | if (is_dp) | |||
| 1183 | args.v3.usPixelClock = cpu_to_le16(dp_clock / 10)((__uint16_t)(dp_clock / 10)); | |||
| 1184 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1185 | args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10)((__uint16_t)((radeon_encoder->pixel_clock / 2) / 10)); | |||
| 1186 | else | |||
| 1187 | args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1188 | } | |||
| 1189 | ||||
| 1190 | if (is_dp) | |||
| 1191 | args.v3.ucLaneNum = dp_lane_count; | |||
| 1192 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1193 | args.v3.ucLaneNum = 8; | |||
| 1194 | else | |||
| 1195 | args.v3.ucLaneNum = 4; | |||
| 1196 | ||||
| 1197 | if (dig->linkb) | |||
| 1198 | args.v3.acConfig.ucLinkSel = 1; | |||
| 1199 | if (dig_encoder & 1) | |||
| 1200 | args.v3.acConfig.ucEncoderSel = 1; | |||
| 1201 | ||||
| 1202 | /* Select the PLL for the PHY | |||
| 1203 | * DP PHY should be clocked from external src if there is | |||
| 1204 | * one. | |||
| 1205 | */ | |||
| 1206 | /* On DCE4, if there is an external clock, it generates the DP ref clock */ | |||
| 1207 | if (is_dp && rdev->clock.dp_extclk) | |||
| 1208 | args.v3.acConfig.ucRefClkSource = 2; /* external src */ | |||
| 1209 | else | |||
| 1210 | args.v3.acConfig.ucRefClkSource = pll_id; | |||
| 1211 | ||||
| 1212 | switch (radeon_encoder->encoder_id) { | |||
| 1213 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1214 | args.v3.acConfig.ucTransmitterSel = 0; | |||
| 1215 | break; | |||
| 1216 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1217 | args.v3.acConfig.ucTransmitterSel = 1; | |||
| 1218 | break; | |||
| 1219 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1220 | args.v3.acConfig.ucTransmitterSel = 2; | |||
| 1221 | break; | |||
| 1222 | } | |||
| 1223 | ||||
| 1224 | if (is_dp) | |||
| 1225 | args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */ | |||
| 1226 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )))) { | |||
| 1227 | if (dig->coherent_mode) | |||
| 1228 | args.v3.acConfig.fCoherentMode = 1; | |||
| 1229 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1230 | args.v3.acConfig.fDualLinkConnector = 1; | |||
| 1231 | } | |||
| 1232 | break; | |||
| 1233 | case 4: | |||
| 1234 | args.v4.ucAction = action; | |||
| 1235 | if (action == ATOM_TRANSMITTER_ACTION_INIT7) { | |||
| 1236 | args.v4.usInitInfo = cpu_to_le16(connector_object_id)((__uint16_t)(connector_object_id)); | |||
| 1237 | } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH11) { | |||
| 1238 | args.v4.asMode.ucLaneSel = lane_num; | |||
| 1239 | args.v4.asMode.ucLaneSet = lane_set; | |||
| 1240 | } else { | |||
| 1241 | if (is_dp) | |||
| 1242 | args.v4.usPixelClock = cpu_to_le16(dp_clock / 10)((__uint16_t)(dp_clock / 10)); | |||
| 1243 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1244 | args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10)((__uint16_t)((radeon_encoder->pixel_clock / 2) / 10)); | |||
| 1245 | else | |||
| 1246 | args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1247 | } | |||
| 1248 | ||||
| 1249 | if (is_dp) | |||
| 1250 | args.v4.ucLaneNum = dp_lane_count; | |||
| 1251 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1252 | args.v4.ucLaneNum = 8; | |||
| 1253 | else | |||
| 1254 | args.v4.ucLaneNum = 4; | |||
| 1255 | ||||
| 1256 | if (dig->linkb) | |||
| 1257 | args.v4.acConfig.ucLinkSel = 1; | |||
| 1258 | if (dig_encoder & 1) | |||
| 1259 | args.v4.acConfig.ucEncoderSel = 1; | |||
| 1260 | ||||
| 1261 | /* Select the PLL for the PHY | |||
| 1262 | * DP PHY should be clocked from external src if there is | |||
| 1263 | * one. | |||
| 1264 | */ | |||
| 1265 | /* On DCE5 DCPLL usually generates the DP ref clock */ | |||
| 1266 | if (is_dp) { | |||
| 1267 | if (rdev->clock.dp_extclk) | |||
| 1268 | args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK3; | |||
| 1269 | else | |||
| 1270 | args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL2; | |||
| 1271 | } else | |||
| 1272 | args.v4.acConfig.ucRefClkSource = pll_id; | |||
| 1273 | ||||
| 1274 | switch (radeon_encoder->encoder_id) { | |||
| 1275 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1276 | args.v4.acConfig.ucTransmitterSel = 0; | |||
| 1277 | break; | |||
| 1278 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1279 | args.v4.acConfig.ucTransmitterSel = 1; | |||
| 1280 | break; | |||
| 1281 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1282 | args.v4.acConfig.ucTransmitterSel = 2; | |||
| 1283 | break; | |||
| 1284 | } | |||
| 1285 | ||||
| 1286 | if (is_dp) | |||
| 1287 | args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */ | |||
| 1288 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )))) { | |||
| 1289 | if (dig->coherent_mode) | |||
| 1290 | args.v4.acConfig.fCoherentMode = 1; | |||
| 1291 | if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1292 | args.v4.acConfig.fDualLinkConnector = 1; | |||
| 1293 | } | |||
| 1294 | break; | |||
| 1295 | case 5: | |||
| 1296 | args.v5.ucAction = action; | |||
| 1297 | if (is_dp) | |||
| 1298 | args.v5.usSymClock = cpu_to_le16(dp_clock / 10)((__uint16_t)(dp_clock / 10)); | |||
| 1299 | else | |||
| 1300 | args.v5.usSymClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1301 | ||||
| 1302 | switch (radeon_encoder->encoder_id) { | |||
| 1303 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1304 | if (dig->linkb) | |||
| 1305 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB1; | |||
| 1306 | else | |||
| 1307 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA0; | |||
| 1308 | break; | |||
| 1309 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1310 | if (dig->linkb) | |||
| 1311 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD3; | |||
| 1312 | else | |||
| 1313 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC2; | |||
| 1314 | break; | |||
| 1315 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1316 | if (dig->linkb) | |||
| 1317 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF5; | |||
| 1318 | else | |||
| 1319 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE4; | |||
| 1320 | break; | |||
| 1321 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 1322 | args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYG6; | |||
| 1323 | break; | |||
| 1324 | } | |||
| 1325 | if (is_dp) | |||
| 1326 | args.v5.ucLaneNum = dp_lane_count; | |||
| 1327 | else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1328 | args.v5.ucLaneNum = 8; | |||
| 1329 | else | |||
| 1330 | args.v5.ucLaneNum = 4; | |||
| 1331 | args.v5.ucConnObjId = connector_object_id; | |||
| 1332 | args.v5.ucDigMode = atombios_get_encoder_mode(encoder); | |||
| 1333 | ||||
| 1334 | if (is_dp && rdev->clock.dp_extclk) | |||
| 1335 | args.v5.asConfig.ucPhyClkSrcId = ENCODER_REFCLK_SRC_EXTCLK3; | |||
| 1336 | else | |||
| 1337 | args.v5.asConfig.ucPhyClkSrcId = pll_id; | |||
| 1338 | ||||
| 1339 | if (is_dp) | |||
| 1340 | args.v5.asConfig.ucCoherentMode = 1; /* DP requires coherent */ | |||
| 1341 | else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )))) { | |||
| 1342 | if (dig->coherent_mode) | |||
| 1343 | args.v5.asConfig.ucCoherentMode = 1; | |||
| 1344 | } | |||
| 1345 | if (hpd_id == RADEON_HPD_NONE) | |||
| 1346 | args.v5.asConfig.ucHPDSel = 0; | |||
| 1347 | else | |||
| 1348 | args.v5.asConfig.ucHPDSel = hpd_id + 1; | |||
| 1349 | args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder); | |||
| 1350 | args.v5.ucDPLaneSet = lane_set; | |||
| 1351 | break; | |||
| 1352 | default: | |||
| 1353 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 1354 | break; | |||
| 1355 | } | |||
| 1356 | break; | |||
| 1357 | default: | |||
| 1358 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev)__drm_err("Unknown table version %d, %d\n", frev, crev); | |||
| 1359 | break; | |||
| 1360 | } | |||
| 1361 | ||||
| 1362 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1363 | } | |||
| 1364 | ||||
| 1365 | void | |||
| 1366 | atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) | |||
| 1367 | { | |||
| 1368 | atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1); | |||
| 1369 | } | |||
| 1370 | ||||
| 1371 | bool_Bool | |||
| 1372 | atombios_set_edp_panel_power(struct drm_connector *connector, int action) | |||
| 1373 | { | |||
| 1374 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 1375 | struct drm_device *dev = radeon_connector->base.dev; | |||
| 1376 | struct radeon_device *rdev = dev->dev_private; | |||
| 1377 | union dig_transmitter_control args; | |||
| 1378 | int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DIG1TransmitterControl )/sizeof(USHORT)); | |||
| 1379 | uint8_t frev, crev; | |||
| 1380 | ||||
| 1381 | if (connector->connector_type != DRM_MODE_CONNECTOR_eDP14) | |||
| 1382 | goto done; | |||
| 1383 | ||||
| 1384 | if (!ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) | |||
| 1385 | goto done; | |||
| 1386 | ||||
| 1387 | if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON12) && | |||
| 1388 | (action != ATOM_TRANSMITTER_ACTION_POWER_OFF13)) | |||
| 1389 | goto done; | |||
| 1390 | ||||
| 1391 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 1392 | goto done; | |||
| 1393 | ||||
| 1394 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 1395 | ||||
| 1396 | args.v1.ucAction = action; | |||
| 1397 | ||||
| 1398 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1399 | ||||
| 1400 | /* wait for the panel to power up */ | |||
| 1401 | if (action == ATOM_TRANSMITTER_ACTION_POWER_ON12) { | |||
| 1402 | int i; | |||
| 1403 | ||||
| 1404 | for (i = 0; i < 300; i++) { | |||
| 1405 | if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)(rdev)->asic->hpd.sense((rdev), (radeon_connector->hpd .hpd))) | |||
| 1406 | return true1; | |||
| 1407 | mdelay(1); | |||
| 1408 | } | |||
| 1409 | return false0; | |||
| 1410 | } | |||
| 1411 | done: | |||
| 1412 | return true1; | |||
| 1413 | } | |||
| 1414 | ||||
| 1415 | union external_encoder_control { | |||
| 1416 | EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; | |||
| 1417 | EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; | |||
| 1418 | }; | |||
| 1419 | ||||
| 1420 | static void | |||
| 1421 | atombios_external_encoder_setup(struct drm_encoder *encoder, | |||
| 1422 | struct drm_encoder *ext_encoder, | |||
| 1423 | int action) | |||
| 1424 | { | |||
| 1425 | struct drm_device *dev = encoder->dev; | |||
| 1426 | struct radeon_device *rdev = dev->dev_private; | |||
| 1427 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1428 | struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (ext_encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof(struct radeon_encoder, base) );}); | |||
| 1429 | union external_encoder_control args; | |||
| 1430 | struct drm_connector *connector; | |||
| 1431 | int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, ExternalEncoderControl )/sizeof(USHORT)); | |||
| 1432 | u8 frev, crev; | |||
| 1433 | int dp_clock = 0; | |||
| 1434 | int dp_lane_count = 0; | |||
| 1435 | int connector_object_id = 0; | |||
| 1436 | u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK0x0700) >> ENUM_ID_SHIFT0x08; | |||
| 1437 | ||||
| 1438 | if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT0x07) | |||
| 1439 | connector = radeon_get_connector_for_encoder_init(encoder); | |||
| 1440 | else | |||
| 1441 | connector = radeon_get_connector_for_encoder(encoder); | |||
| 1442 | ||||
| 1443 | if (connector) { | |||
| 1444 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 1445 | struct radeon_connector_atom_dig *dig_connector = | |||
| 1446 | radeon_connector->con_priv; | |||
| 1447 | ||||
| 1448 | dp_clock = dig_connector->dp_clock; | |||
| 1449 | dp_lane_count = dig_connector->dp_lane_count; | |||
| 1450 | connector_object_id = | |||
| 1451 | (radeon_connector->connector_object_id & OBJECT_ID_MASK0x00FF) >> OBJECT_ID_SHIFT0x00; | |||
| 1452 | } | |||
| 1453 | ||||
| 1454 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 1455 | ||||
| 1456 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 1457 | return; | |||
| 1458 | ||||
| 1459 | switch (frev) { | |||
| 1460 | case 1: | |||
| 1461 | /* no params on frev 1 */ | |||
| 1462 | break; | |||
| 1463 | case 2: | |||
| 1464 | switch (crev) { | |||
| 1465 | case 1: | |||
| 1466 | case 2: | |||
| 1467 | args.v1.sDigEncoder.ucAction = action; | |||
| 1468 | args.v1.sDigEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1469 | args.v1.sDigEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); | |||
| 1470 | ||||
| 1471 | if (ENCODER_MODE_IS_DP(args.v1.sDigEncoder.ucEncoderMode)(((args.v1.sDigEncoder.ucEncoderMode) == 0) || ((args.v1.sDigEncoder .ucEncoderMode) == 5))) { | |||
| 1472 | if (dp_clock == 270000) | |||
| 1473 | args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ0x01; | |||
| 1474 | args.v1.sDigEncoder.ucLaneNum = dp_lane_count; | |||
| 1475 | } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1476 | args.v1.sDigEncoder.ucLaneNum = 8; | |||
| 1477 | else | |||
| 1478 | args.v1.sDigEncoder.ucLaneNum = 4; | |||
| 1479 | break; | |||
| 1480 | case 3: | |||
| 1481 | args.v3.sExtEncoder.ucAction = action; | |||
| 1482 | if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT0x07) | |||
| 1483 | args.v3.sExtEncoder.usConnectorId = cpu_to_le16(connector_object_id)((__uint16_t)(connector_object_id)); | |||
| 1484 | else | |||
| 1485 | args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10)((__uint16_t)(radeon_encoder->pixel_clock / 10)); | |||
| 1486 | args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); | |||
| 1487 | ||||
| 1488 | if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)(((args.v3.sExtEncoder.ucEncoderMode) == 0) || ((args.v3.sExtEncoder .ucEncoderMode) == 5))) { | |||
| 1489 | if (dp_clock == 270000) | |||
| 1490 | args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ0x01; | |||
| 1491 | else if (dp_clock == 540000) | |||
| 1492 | args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ0x02; | |||
| 1493 | args.v3.sExtEncoder.ucLaneNum = dp_lane_count; | |||
| 1494 | } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) | |||
| 1495 | args.v3.sExtEncoder.ucLaneNum = 8; | |||
| 1496 | else | |||
| 1497 | args.v3.sExtEncoder.ucLaneNum = 4; | |||
| 1498 | switch (ext_enum) { | |||
| 1499 | case GRAPH_OBJECT_ENUM_ID10x01: | |||
| 1500 | args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER10x00; | |||
| 1501 | break; | |||
| 1502 | case GRAPH_OBJECT_ENUM_ID20x02: | |||
| 1503 | args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER20x10; | |||
| 1504 | break; | |||
| 1505 | case GRAPH_OBJECT_ENUM_ID30x03: | |||
| 1506 | args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER30x20; | |||
| 1507 | break; | |||
| 1508 | } | |||
| 1509 | args.v3.sExtEncoder.ucBitPerColor = radeon_atom_get_bpc(encoder); | |||
| 1510 | break; | |||
| 1511 | default: | |||
| 1512 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev)__drm_err("Unknown table version: %d, %d\n", frev, crev); | |||
| 1513 | return; | |||
| 1514 | } | |||
| 1515 | break; | |||
| 1516 | default: | |||
| 1517 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev)__drm_err("Unknown table version: %d, %d\n", frev, crev); | |||
| 1518 | return; | |||
| 1519 | } | |||
| 1520 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1521 | } | |||
| 1522 | ||||
| 1523 | static void | |||
| 1524 | atombios_yuv_setup(struct drm_encoder *encoder, bool_Bool enable) | |||
| 1525 | { | |||
| 1526 | struct drm_device *dev = encoder->dev; | |||
| 1527 | struct radeon_device *rdev = dev->dev_private; | |||
| 1528 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1529 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc)({ const __typeof( ((struct radeon_crtc *)0)->base ) *__mptr = (encoder->crtc); (struct radeon_crtc *)( (char *)__mptr - __builtin_offsetof(struct radeon_crtc, base) );}); | |||
| 1530 | ENABLE_YUV_PS_ALLOCATIONENABLE_YUV_PARAMETERS args; | |||
| 1531 | int index = GetIndexIntoMasterTable(COMMAND, EnableYUV)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, GetDispObjectInfo )/sizeof(USHORT)); | |||
| 1532 | uint32_t temp, reg; | |||
| 1533 | ||||
| 1534 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 1535 | ||||
| 1536 | if (rdev->family >= CHIP_R600) | |||
| 1537 | reg = R600_BIOS_3_SCRATCH0x1730; | |||
| 1538 | else | |||
| 1539 | reg = RADEON_BIOS_3_SCRATCH0x001c; | |||
| 1540 | ||||
| 1541 | /* XXX: fix up scratch reg handling */ | |||
| 1542 | temp = RREG32(reg)r100_mm_rreg(rdev, (reg), 0); | |||
| 1543 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1544 | WREG32(reg, (ATOM_S3_TV1_ACTIVE |r100_mm_wreg(rdev, (reg), ((0x00000004L | (radeon_crtc->crtc_id << 18))), 0) | |||
| 1545 | (radeon_crtc->crtc_id << 18)))r100_mm_wreg(rdev, (reg), ((0x00000004L | (radeon_crtc->crtc_id << 18))), 0); | |||
| 1546 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1547 | WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)))r100_mm_wreg(rdev, (reg), ((0x00000100L | (radeon_crtc->crtc_id << 24))), 0); | |||
| 1548 | else | |||
| 1549 | WREG32(reg, 0)r100_mm_wreg(rdev, (reg), (0), 0); | |||
| 1550 | ||||
| 1551 | if (enable) | |||
| 1552 | args.ucEnable = ATOM_ENABLE1; | |||
| 1553 | args.ucCRTC = radeon_crtc->crtc_id; | |||
| 1554 | ||||
| 1555 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1556 | ||||
| 1557 | WREG32(reg, temp)r100_mm_wreg(rdev, (reg), (temp), 0); | |||
| 1558 | } | |||
| 1559 | ||||
| 1560 | static void | |||
| 1561 | radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode) | |||
| 1562 | { | |||
| 1563 | struct drm_device *dev = encoder->dev; | |||
| 1564 | struct radeon_device *rdev = dev->dev_private; | |||
| 1565 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1566 | DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATIONDISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS args; | |||
| 1567 | int index = 0; | |||
| 1568 | ||||
| 1569 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 1570 | ||||
| 1571 | switch (radeon_encoder->encoder_id) { | |||
| 1572 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 1573 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 1574 | index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, TMDSAOutputControl )/sizeof(USHORT)); | |||
| 1575 | break; | |||
| 1576 | case ENCODER_OBJECT_ID_INTERNAL_DVO10x0B: | |||
| 1577 | case ENCODER_OBJECT_ID_INTERNAL_DDI0x19: | |||
| 1578 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 1579 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DVOOutputControl )/sizeof(USHORT)); | |||
| 1580 | break; | |||
| 1581 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 1582 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, HW_Misc_Operation )/sizeof(USHORT)); | |||
| 1583 | break; | |||
| 1584 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 1585 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) | |||
| 1586 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, HW_Misc_Operation )/sizeof(USHORT)); | |||
| 1587 | else | |||
| 1588 | index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, LVTMAOutputControl )/sizeof(USHORT)); | |||
| 1589 | break; | |||
| 1590 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 1591 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 1592 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1593 | index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, Gfx_Harvesting )/sizeof(USHORT)); | |||
| 1594 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1595 | index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, CV1OutputControl )/sizeof(USHORT)); | |||
| 1596 | else | |||
| 1597 | index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DAC1OutputControl )/sizeof(USHORT)); | |||
| 1598 | break; | |||
| 1599 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 1600 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 1601 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1602 | index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, Gfx_Harvesting )/sizeof(USHORT)); | |||
| 1603 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1604 | index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, CV1OutputControl )/sizeof(USHORT)); | |||
| 1605 | else | |||
| 1606 | index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DAC2OutputControl )/sizeof(USHORT)); | |||
| 1607 | break; | |||
| 1608 | default: | |||
| 1609 | return; | |||
| 1610 | } | |||
| 1611 | ||||
| 1612 | switch (mode) { | |||
| 1613 | case DRM_MODE_DPMS_ON0: | |||
| 1614 | args.ucAction = ATOM_ENABLE1; | |||
| 1615 | /* workaround for DVOOutputControl on some RS690 systems */ | |||
| 1616 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI0x19) { | |||
| 1617 | u32 reg = RREG32(RADEON_BIOS_3_SCRATCH)r100_mm_rreg(rdev, (0x001c), 0); | |||
| 1618 | WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE)r100_mm_wreg(rdev, (0x001c), (reg & ~0x00000200L), 0); | |||
| 1619 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1620 | WREG32(RADEON_BIOS_3_SCRATCH, reg)r100_mm_wreg(rdev, (0x001c), (reg), 0); | |||
| 1621 | } else | |||
| 1622 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1623 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 1624 | if (rdev->mode_info.bl_encoder) { | |||
| 1625 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 1626 | ||||
| 1627 | atombios_set_backlight_level(radeon_encoder, dig->backlight_level); | |||
| 1628 | } else { | |||
| 1629 | args.ucAction = ATOM_LCD_BLON(1 +2); | |||
| 1630 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1631 | } | |||
| 1632 | } | |||
| 1633 | break; | |||
| 1634 | case DRM_MODE_DPMS_STANDBY1: | |||
| 1635 | case DRM_MODE_DPMS_SUSPEND2: | |||
| 1636 | case DRM_MODE_DPMS_OFF3: | |||
| 1637 | args.ucAction = ATOM_DISABLE0; | |||
| 1638 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1639 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 1640 | args.ucAction = ATOM_LCD_BLOFF(0 +2); | |||
| 1641 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1642 | } | |||
| 1643 | break; | |||
| 1644 | } | |||
| 1645 | } | |||
| 1646 | ||||
| 1647 | static void | |||
| 1648 | radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
| 1649 | { | |||
| 1650 | struct drm_device *dev = encoder->dev; | |||
| 1651 | struct radeon_device *rdev = dev->dev_private; | |||
| 1652 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1653 | struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); | |||
| 1654 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 1655 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |||
| 1656 | struct radeon_connector *radeon_connector = NULL((void *)0); | |||
| 1657 | struct radeon_connector_atom_dig *radeon_dig_connector = NULL((void *)0); | |||
| 1658 | bool_Bool travis_quirk = false0; | |||
| 1659 | ||||
| 1660 | if (connector) { | |||
| 1661 | radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 1662 | radeon_dig_connector = radeon_connector->con_priv; | |||
| 1663 | if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == | |||
| 1664 | ENCODER_OBJECT_ID_TRAVIS0x23) && | |||
| 1665 | (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) && | |||
| 1666 | !ASIC_IS_DCE5(rdev)((rdev->family >= CHIP_BARTS))) | |||
| 1667 | travis_quirk = true1; | |||
| 1668 | } | |||
| 1669 | ||||
| 1670 | switch (mode) { | |||
| 1671 | case DRM_MODE_DPMS_ON0: | |||
| 1672 | if (ASIC_IS_DCE41(rdev)((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP)) || ASIC_IS_DCE5(rdev)((rdev->family >= CHIP_BARTS))) { | |||
| 1673 | if (!connector) | |||
| 1674 | dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE0x00; | |||
| 1675 | else | |||
| 1676 | dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); | |||
| 1677 | ||||
| 1678 | /* setup and enable the encoder */ | |||
| 1679 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP0x0f, 0); | |||
| 1680 | atombios_dig_encoder_setup(encoder, | |||
| 1681 | ATOM_ENCODER_CMD_SETUP_PANEL_MODE0x10, | |||
| 1682 | dig->panel_mode); | |||
| 1683 | if (ext_encoder) { | |||
| 1684 | if (ASIC_IS_DCE41(rdev)((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP)) || ASIC_IS_DCE61(rdev)((rdev->family >= CHIP_ARUBA) && (rdev->flags & RADEON_IS_IGP))) | |||
| 1685 | atombios_external_encoder_setup(encoder, ext_encoder, | |||
| 1686 | EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP0x0f); | |||
| 1687 | } | |||
| 1688 | } else if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) { | |||
| 1689 | /* setup and enable the encoder */ | |||
| 1690 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP0x0f, 0); | |||
| 1691 | } else { | |||
| 1692 | /* setup and enable the encoder and transmitter */ | |||
| 1693 | atombios_dig_encoder_setup(encoder, ATOM_ENABLE1, 0); | |||
| 1694 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP10, 0, 0); | |||
| 1695 | } | |||
| 1696 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))(((atombios_get_encoder_mode(encoder)) == 0) || ((atombios_get_encoder_mode (encoder)) == 5)) && connector) { | |||
| 1697 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP14) { | |||
| 1698 | atombios_set_edp_panel_power(connector, | |||
| 1699 | ATOM_TRANSMITTER_ACTION_POWER_ON12); | |||
| 1700 | radeon_dig_connector->edp_on = true1; | |||
| 1701 | } | |||
| 1702 | } | |||
| 1703 | /* enable the transmitter */ | |||
| 1704 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE1, 0, 0); | |||
| 1705 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))(((atombios_get_encoder_mode(encoder)) == 0) || ((atombios_get_encoder_mode (encoder)) == 5)) && connector) { | |||
| 1706 | /* DP_SET_POWER_D0 is set in radeon_dp_link_train */ | |||
| 1707 | radeon_dp_link_train(encoder, connector); | |||
| 1708 | if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) | |||
| 1709 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON0x0d, 0); | |||
| 1710 | } | |||
| 1711 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 1712 | if (rdev->mode_info.bl_encoder) | |||
| 1713 | atombios_set_backlight_level(radeon_encoder, dig->backlight_level); | |||
| 1714 | else | |||
| 1715 | atombios_dig_transmitter_setup(encoder, | |||
| 1716 | ATOM_TRANSMITTER_ACTION_LCD_BLON3, 0, 0); | |||
| 1717 | } | |||
| 1718 | if (ext_encoder) | |||
| 1719 | atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE1); | |||
| 1720 | break; | |||
| 1721 | case DRM_MODE_DPMS_STANDBY1: | |||
| 1722 | case DRM_MODE_DPMS_SUSPEND2: | |||
| 1723 | case DRM_MODE_DPMS_OFF3: | |||
| 1724 | ||||
| 1725 | if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) { | |||
| 1726 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))(((atombios_get_encoder_mode(encoder)) == 0) || ((atombios_get_encoder_mode (encoder)) == 5)) && connector) | |||
| 1727 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF0x0c, 0); | |||
| 1728 | } | |||
| 1729 | if (ext_encoder) | |||
| 1730 | atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE0); | |||
| 1731 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) | |||
| 1732 | atombios_dig_transmitter_setup(encoder, | |||
| 1733 | ATOM_TRANSMITTER_ACTION_LCD_BLOFF2, 0, 0); | |||
| 1734 | ||||
| 1735 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))(((atombios_get_encoder_mode(encoder)) == 0) || ((atombios_get_encoder_mode (encoder)) == 5)) && | |||
| 1736 | connector && !travis_quirk) | |||
| 1737 | radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D30x2); | |||
| 1738 | if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) { | |||
| 1739 | /* disable the transmitter */ | |||
| 1740 | atombios_dig_transmitter_setup(encoder, | |||
| 1741 | ATOM_TRANSMITTER_ACTION_DISABLE0, 0, 0); | |||
| 1742 | } else { | |||
| 1743 | /* disable the encoder and transmitter */ | |||
| 1744 | atombios_dig_transmitter_setup(encoder, | |||
| 1745 | ATOM_TRANSMITTER_ACTION_DISABLE0, 0, 0); | |||
| 1746 | atombios_dig_encoder_setup(encoder, ATOM_DISABLE0, 0); | |||
| 1747 | } | |||
| 1748 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder))(((atombios_get_encoder_mode(encoder)) == 0) || ((atombios_get_encoder_mode (encoder)) == 5)) && connector) { | |||
| 1749 | if (travis_quirk) | |||
| 1750 | radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D30x2); | |||
| 1751 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP14) { | |||
| 1752 | atombios_set_edp_panel_power(connector, | |||
| 1753 | ATOM_TRANSMITTER_ACTION_POWER_OFF13); | |||
| 1754 | radeon_dig_connector->edp_on = false0; | |||
| 1755 | } | |||
| 1756 | } | |||
| 1757 | break; | |||
| 1758 | } | |||
| 1759 | } | |||
| 1760 | ||||
| 1761 | static void | |||
| 1762 | radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 1763 | { | |||
| 1764 | struct drm_device *dev = encoder->dev; | |||
| 1765 | struct radeon_device *rdev = dev->dev_private; | |||
| 1766 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1767 | int encoder_mode = atombios_get_encoder_mode(encoder); | |||
| 1768 | ||||
| 1769 | DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",___drm_dbg(((void *)0), DRM_UT_KMS, "encoder dpms %d to mode %d, devices %08x, active_devices %08x\n" , radeon_encoder->encoder_id, mode, radeon_encoder->devices , radeon_encoder->active_device) | |||
| 1770 | radeon_encoder->encoder_id, mode, radeon_encoder->devices,___drm_dbg(((void *)0), DRM_UT_KMS, "encoder dpms %d to mode %d, devices %08x, active_devices %08x\n" , radeon_encoder->encoder_id, mode, radeon_encoder->devices , radeon_encoder->active_device) | |||
| 1771 | radeon_encoder->active_device)___drm_dbg(((void *)0), DRM_UT_KMS, "encoder dpms %d to mode %d, devices %08x, active_devices %08x\n" , radeon_encoder->encoder_id, mode, radeon_encoder->devices , radeon_encoder->active_device); | |||
| 1772 | ||||
| 1773 | if ((radeon_audio != 0) && | |||
| 1774 | ((encoder_mode == ATOM_ENCODER_MODE_HDMI3) || | |||
| 1775 | ENCODER_MODE_IS_DP(encoder_mode)(((encoder_mode) == 0) || ((encoder_mode) == 5)))) | |||
| 1776 | radeon_audio_dpms(encoder, mode); | |||
| 1777 | ||||
| 1778 | switch (radeon_encoder->encoder_id) { | |||
| 1779 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 1780 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 1781 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 1782 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 1783 | case ENCODER_OBJECT_ID_INTERNAL_DVO10x0B: | |||
| 1784 | case ENCODER_OBJECT_ID_INTERNAL_DDI0x19: | |||
| 1785 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 1786 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 1787 | radeon_atom_encoder_dpms_avivo(encoder, mode); | |||
| 1788 | break; | |||
| 1789 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1790 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1791 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1792 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 1793 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 1794 | radeon_atom_encoder_dpms_dig(encoder, mode); | |||
| 1795 | break; | |||
| 1796 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 1797 | if (ASIC_IS_DCE5(rdev)((rdev->family >= CHIP_BARTS))) { | |||
| 1798 | switch (mode) { | |||
| 1799 | case DRM_MODE_DPMS_ON0: | |||
| 1800 | atombios_dvo_setup(encoder, ATOM_ENABLE1); | |||
| 1801 | break; | |||
| 1802 | case DRM_MODE_DPMS_STANDBY1: | |||
| 1803 | case DRM_MODE_DPMS_SUSPEND2: | |||
| 1804 | case DRM_MODE_DPMS_OFF3: | |||
| 1805 | atombios_dvo_setup(encoder, ATOM_DISABLE0); | |||
| 1806 | break; | |||
| 1807 | } | |||
| 1808 | } else if (ASIC_IS_DCE3(rdev)((rdev->family >= CHIP_RV620))) | |||
| 1809 | radeon_atom_encoder_dpms_dig(encoder, mode); | |||
| 1810 | else | |||
| 1811 | radeon_atom_encoder_dpms_avivo(encoder, mode); | |||
| 1812 | break; | |||
| 1813 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 1814 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 1815 | if (ASIC_IS_DCE5(rdev)((rdev->family >= CHIP_BARTS))) { | |||
| 1816 | switch (mode) { | |||
| 1817 | case DRM_MODE_DPMS_ON0: | |||
| 1818 | atombios_dac_setup(encoder, ATOM_ENABLE1); | |||
| 1819 | break; | |||
| 1820 | case DRM_MODE_DPMS_STANDBY1: | |||
| 1821 | case DRM_MODE_DPMS_SUSPEND2: | |||
| 1822 | case DRM_MODE_DPMS_OFF3: | |||
| 1823 | atombios_dac_setup(encoder, ATOM_DISABLE0); | |||
| 1824 | break; | |||
| 1825 | } | |||
| 1826 | } else | |||
| 1827 | radeon_atom_encoder_dpms_avivo(encoder, mode); | |||
| 1828 | break; | |||
| 1829 | default: | |||
| 1830 | return; | |||
| 1831 | } | |||
| 1832 | ||||
| 1833 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON0) ? true1 : false0); | |||
| 1834 | ||||
| 1835 | } | |||
| 1836 | ||||
| 1837 | union crtc_source_param { | |||
| 1838 | SELECT_CRTC_SOURCE_PS_ALLOCATIONSELECT_CRTC_SOURCE_PARAMETERS v1; | |||
| 1839 | SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; | |||
| 1840 | }; | |||
| 1841 | ||||
| 1842 | static void | |||
| 1843 | atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | |||
| 1844 | { | |||
| 1845 | struct drm_device *dev = encoder->dev; | |||
| 1846 | struct radeon_device *rdev = dev->dev_private; | |||
| 1847 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1848 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc)({ const __typeof( ((struct radeon_crtc *)0)->base ) *__mptr = (encoder->crtc); (struct radeon_crtc *)( (char *)__mptr - __builtin_offsetof(struct radeon_crtc, base) );}); | |||
| 1849 | union crtc_source_param args; | |||
| 1850 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, SelectCRTC_Source )/sizeof(USHORT)); | |||
| 1851 | uint8_t frev, crev; | |||
| 1852 | struct radeon_encoder_atom_dig *dig; | |||
| 1853 | ||||
| 1854 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 1855 | ||||
| 1856 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 1857 | return; | |||
| 1858 | ||||
| 1859 | switch (frev) { | |||
| 1860 | case 1: | |||
| 1861 | switch (crev) { | |||
| 1862 | case 1: | |||
| 1863 | default: | |||
| 1864 | if (ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600))) | |||
| 1865 | args.v1.ucCRTC = radeon_crtc->crtc_id; | |||
| 1866 | else { | |||
| 1867 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC10x04) | |||
| 1868 | args.v1.ucCRTC = radeon_crtc->crtc_id; | |||
| 1869 | else | |||
| 1870 | args.v1.ucCRTC = radeon_crtc->crtc_id << 2; | |||
| 1871 | } | |||
| 1872 | switch (radeon_encoder->encoder_id) { | |||
| 1873 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 1874 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 1875 | args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX0x00000003; | |||
| 1876 | break; | |||
| 1877 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 1878 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 1879 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT(0x1L << 0x00000001 )) | |||
| 1880 | args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX0x00000001; | |||
| 1881 | else | |||
| 1882 | args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX0x00000009; | |||
| 1883 | break; | |||
| 1884 | case ENCODER_OBJECT_ID_INTERNAL_DVO10x0B: | |||
| 1885 | case ENCODER_OBJECT_ID_INTERNAL_DDI0x19: | |||
| 1886 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 1887 | args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX0x00000007; | |||
| 1888 | break; | |||
| 1889 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 1890 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 1891 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1892 | args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX0x00000002; | |||
| 1893 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1894 | args.v1.ucDevice = ATOM_DEVICE_CV_INDEX0x00000008; | |||
| 1895 | else | |||
| 1896 | args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX0x00000000; | |||
| 1897 | break; | |||
| 1898 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 1899 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 1900 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1901 | args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX0x00000002; | |||
| 1902 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1903 | args.v1.ucDevice = ATOM_DEVICE_CV_INDEX0x00000008; | |||
| 1904 | else | |||
| 1905 | args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX0x00000004; | |||
| 1906 | break; | |||
| 1907 | } | |||
| 1908 | break; | |||
| 1909 | case 2: | |||
| 1910 | args.v2.ucCRTC = radeon_crtc->crtc_id; | |||
| 1911 | if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE0x00) { | |||
| 1912 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |||
| 1913 | ||||
| 1914 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS7) | |||
| 1915 | args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS1; | |||
| 1916 | else if (connector->connector_type == DRM_MODE_CONNECTOR_VGA1) | |||
| 1917 | args.v2.ucEncodeMode = ATOM_ENCODER_MODE_CRT15; | |||
| 1918 | else | |||
| 1919 | args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); | |||
| 1920 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 1921 | args.v2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS1; | |||
| 1922 | } else { | |||
| 1923 | args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); | |||
| 1924 | } | |||
| 1925 | switch (radeon_encoder->encoder_id) { | |||
| 1926 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 1927 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 1928 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 1929 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 1930 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 1931 | dig = radeon_encoder->enc_priv; | |||
| 1932 | switch (dig->dig_encoder) { | |||
| 1933 | case 0: | |||
| 1934 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID0x03; | |||
| 1935 | break; | |||
| 1936 | case 1: | |||
| 1937 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID0x09; | |||
| 1938 | break; | |||
| 1939 | case 2: | |||
| 1940 | args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID0x0a; | |||
| 1941 | break; | |||
| 1942 | case 3: | |||
| 1943 | args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID0x0b; | |||
| 1944 | break; | |||
| 1945 | case 4: | |||
| 1946 | args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID0x0c; | |||
| 1947 | break; | |||
| 1948 | case 5: | |||
| 1949 | args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID0x0d; | |||
| 1950 | break; | |||
| 1951 | case 6: | |||
| 1952 | args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID0x0e; | |||
| 1953 | break; | |||
| 1954 | } | |||
| 1955 | break; | |||
| 1956 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 1957 | args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID0x07; | |||
| 1958 | break; | |||
| 1959 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 1960 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1961 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID0x02; | |||
| 1962 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1963 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID0x02; | |||
| 1964 | else | |||
| 1965 | args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID0x00; | |||
| 1966 | break; | |||
| 1967 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 1968 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 1969 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID0x02; | |||
| 1970 | else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 1971 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID0x02; | |||
| 1972 | else | |||
| 1973 | args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID0x04; | |||
| 1974 | break; | |||
| 1975 | } | |||
| 1976 | break; | |||
| 1977 | } | |||
| 1978 | break; | |||
| 1979 | default: | |||
| 1980 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev)__drm_err("Unknown table version: %d, %d\n", frev, crev); | |||
| 1981 | return; | |||
| 1982 | } | |||
| 1983 | ||||
| 1984 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 1985 | ||||
| 1986 | /* update scratch regs with new routing */ | |||
| 1987 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | |||
| 1988 | } | |||
| 1989 | ||||
| 1990 | static void | |||
| 1991 | atombios_apply_encoder_quirks(struct drm_encoder *encoder, | |||
| 1992 | struct drm_display_mode *mode) | |||
| 1993 | { | |||
| 1994 | struct drm_device *dev = encoder->dev; | |||
| 1995 | struct radeon_device *rdev = dev->dev_private; | |||
| 1996 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 1997 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc)({ const __typeof( ((struct radeon_crtc *)0)->base ) *__mptr = (encoder->crtc); (struct radeon_crtc *)( (char *)__mptr - __builtin_offsetof(struct radeon_crtc, base) );}); | |||
| 1998 | ||||
| 1999 | /* Funky macbooks */ | |||
| 2000 | if ((rdev->pdev->device == 0x71C5) && | |||
| 2001 | (rdev->pdev->subsystem_vendor == 0x106b) && | |||
| 2002 | (rdev->pdev->subsystem_device == 0x0080)) { | |||
| 2003 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT(0x1L << 0x00000001 )) { | |||
| 2004 | uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL)r100_mm_rreg(rdev, (0x7a94), 0); | |||
| 2005 | ||||
| 2006 | lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN(1 << 0); | |||
| 2007 | lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN(1 << 8); | |||
| 2008 | ||||
| 2009 | WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control)r100_mm_wreg(rdev, (0x7a94), (lvtma_bit_depth_control), 0); | |||
| 2010 | } | |||
| 2011 | } | |||
| 2012 | ||||
| 2013 | /* set scaler clears this on some chips */ | |||
| 2014 | if (ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600)) && | |||
| 2015 | (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))))) { | |||
| 2016 | if (ASIC_IS_DCE8(rdev)((rdev->family >= CHIP_BONAIRE))) { | |||
| 2017 | if (mode->flags & DRM_MODE_FLAG_INTERLACE(1<<4)) | |||
| 2018 | WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset,r100_mm_wreg(rdev, (0x6b00 + radeon_crtc->crtc_offset), (( 1 << 3)), 0) | |||
| 2019 | CIK_INTERLEAVE_EN)r100_mm_wreg(rdev, (0x6b00 + radeon_crtc->crtc_offset), (( 1 << 3)), 0); | |||
| 2020 | else | |||
| 2021 | WREG32(CIK_LB_DATA_FORMAT + radeon_crtc->crtc_offset, 0)r100_mm_wreg(rdev, (0x6b00 + radeon_crtc->crtc_offset), (0 ), 0); | |||
| 2022 | } else if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) { | |||
| 2023 | if (mode->flags & DRM_MODE_FLAG_INTERLACE(1<<4)) | |||
| 2024 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,r100_mm_wreg(rdev, (0x6b00 + radeon_crtc->crtc_offset), (( 1 << 0)), 0) | |||
| 2025 | EVERGREEN_INTERLEAVE_EN)r100_mm_wreg(rdev, (0x6b00 + radeon_crtc->crtc_offset), (( 1 << 0)), 0); | |||
| 2026 | else | |||
| 2027 | WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0)r100_mm_wreg(rdev, (0x6b00 + radeon_crtc->crtc_offset), (0 ), 0); | |||
| 2028 | } else { | |||
| 2029 | if (mode->flags & DRM_MODE_FLAG_INTERLACE(1<<4)) | |||
| 2030 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,r100_mm_wreg(rdev, (0x6528 + radeon_crtc->crtc_offset), (( 1 << 0)), 0) | |||
| 2031 | AVIVO_D1MODE_INTERLEAVE_EN)r100_mm_wreg(rdev, (0x6528 + radeon_crtc->crtc_offset), (( 1 << 0)), 0); | |||
| 2032 | else | |||
| 2033 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0)r100_mm_wreg(rdev, (0x6528 + radeon_crtc->crtc_offset), (0 ), 0); | |||
| 2034 | } | |||
| 2035 | } | |||
| 2036 | } | |||
| 2037 | ||||
| 2038 | void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx) | |||
| 2039 | { | |||
| 2040 | if (enc_idx < 0) | |||
| 2041 | return; | |||
| 2042 | rdev->mode_info.active_encoders &= ~(1 << enc_idx); | |||
| 2043 | } | |||
| 2044 | ||||
| 2045 | int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx) | |||
| 2046 | { | |||
| 2047 | struct drm_device *dev = encoder->dev; | |||
| 2048 | struct radeon_device *rdev = dev->dev_private; | |||
| 2049 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc)({ const __typeof( ((struct radeon_crtc *)0)->base ) *__mptr = (encoder->crtc); (struct radeon_crtc *)( (char *)__mptr - __builtin_offsetof(struct radeon_crtc, base) );}); | |||
| 2050 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2051 | struct drm_encoder *test_encoder; | |||
| 2052 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 2053 | uint32_t dig_enc_in_use = 0; | |||
| 2054 | int enc_idx = -1; | |||
| 2055 | ||||
| 2056 | if (fe_idx >= 0) { | |||
| 2057 | enc_idx = fe_idx; | |||
| 2058 | goto assigned; | |||
| 2059 | } | |||
| 2060 | if (ASIC_IS_DCE6(rdev)((rdev->family >= CHIP_ARUBA))) { | |||
| 2061 | /* DCE6 */ | |||
| 2062 | switch (radeon_encoder->encoder_id) { | |||
| 2063 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 2064 | if (dig->linkb) | |||
| 2065 | enc_idx = 1; | |||
| 2066 | else | |||
| 2067 | enc_idx = 0; | |||
| 2068 | break; | |||
| 2069 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 2070 | if (dig->linkb) | |||
| 2071 | enc_idx = 3; | |||
| 2072 | else | |||
| 2073 | enc_idx = 2; | |||
| 2074 | break; | |||
| 2075 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 2076 | if (dig->linkb) | |||
| 2077 | enc_idx = 5; | |||
| 2078 | else | |||
| 2079 | enc_idx = 4; | |||
| 2080 | break; | |||
| 2081 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 2082 | enc_idx = 6; | |||
| 2083 | break; | |||
| 2084 | } | |||
| 2085 | goto assigned; | |||
| 2086 | } else if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) { | |||
| 2087 | /* DCE4/5 */ | |||
| 2088 | if (ASIC_IS_DCE41(rdev)((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP)) && !ASIC_IS_DCE61(rdev)((rdev->family >= CHIP_ARUBA) && (rdev->flags & RADEON_IS_IGP))) { | |||
| 2089 | /* ontario follows DCE4 */ | |||
| 2090 | if (rdev->family == CHIP_PALM) { | |||
| 2091 | if (dig->linkb) | |||
| 2092 | enc_idx = 1; | |||
| 2093 | else | |||
| 2094 | enc_idx = 0; | |||
| 2095 | } else | |||
| 2096 | /* llano follows DCE3.2 */ | |||
| 2097 | enc_idx = radeon_crtc->crtc_id; | |||
| 2098 | } else { | |||
| 2099 | switch (radeon_encoder->encoder_id) { | |||
| 2100 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 2101 | if (dig->linkb) | |||
| 2102 | enc_idx = 1; | |||
| 2103 | else | |||
| 2104 | enc_idx = 0; | |||
| 2105 | break; | |||
| 2106 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 2107 | if (dig->linkb) | |||
| 2108 | enc_idx = 3; | |||
| 2109 | else | |||
| 2110 | enc_idx = 2; | |||
| 2111 | break; | |||
| 2112 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 2113 | if (dig->linkb) | |||
| 2114 | enc_idx = 5; | |||
| 2115 | else | |||
| 2116 | enc_idx = 4; | |||
| 2117 | break; | |||
| 2118 | } | |||
| 2119 | } | |||
| 2120 | goto assigned; | |||
| 2121 | } | |||
| 2122 | ||||
| 2123 | /* | |||
| 2124 | * On DCE32 any encoder can drive any block so usually just use crtc id, | |||
| 2125 | * but Apple thinks different at least on iMac10,1, so there use linkb, | |||
| 2126 | * otherwise the internal eDP panel will stay dark. | |||
| 2127 | */ | |||
| 2128 | if (ASIC_IS_DCE32(rdev)((rdev->family >= CHIP_RV730))) { | |||
| 2129 | if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1")) | |||
| 2130 | enc_idx = (dig->linkb) ? 1 : 0; | |||
| 2131 | else | |||
| 2132 | enc_idx = radeon_crtc->crtc_id; | |||
| 2133 | ||||
| 2134 | goto assigned; | |||
| 2135 | } | |||
| 2136 | ||||
| 2137 | /* on DCE3 - LVTMA can only be driven by DIGB */ | |||
| 2138 | list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head)for (test_encoder = ({ const __typeof( ((__typeof(*test_encoder ) *)0)->head ) *__mptr = ((&dev->mode_config.encoder_list )->next); (__typeof(*test_encoder) *)( (char *)__mptr - __builtin_offsetof (__typeof(*test_encoder), head) );}); &test_encoder->head != (&dev->mode_config.encoder_list); test_encoder = ( { const __typeof( ((__typeof(*test_encoder) *)0)->head ) * __mptr = (test_encoder->head.next); (__typeof(*test_encoder ) *)( (char *)__mptr - __builtin_offsetof(__typeof(*test_encoder ), head) );})) { | |||
| 2139 | struct radeon_encoder *radeon_test_encoder; | |||
| 2140 | ||||
| 2141 | if (encoder == test_encoder) | |||
| 2142 | continue; | |||
| 2143 | ||||
| 2144 | if (!radeon_encoder_is_digital(test_encoder)) | |||
| 2145 | continue; | |||
| 2146 | ||||
| 2147 | radeon_test_encoder = to_radeon_encoder(test_encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (test_encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof(struct radeon_encoder, base) );}); | |||
| 2148 | dig = radeon_test_encoder->enc_priv; | |||
| 2149 | ||||
| 2150 | if (dig->dig_encoder >= 0) | |||
| 2151 | dig_enc_in_use |= (1 << dig->dig_encoder); | |||
| 2152 | } | |||
| 2153 | ||||
| 2154 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F) { | |||
| 2155 | if (dig_enc_in_use & 0x2) | |||
| 2156 | DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n")__drm_err("LVDS required digital encoder 2 but it was in use - stealing\n" ); | |||
| 2157 | return 1; | |||
| 2158 | } | |||
| 2159 | if (!(dig_enc_in_use & 1)) | |||
| 2160 | return 0; | |||
| 2161 | return 1; | |||
| 2162 | ||||
| 2163 | assigned: | |||
| 2164 | if (enc_idx == -1) { | |||
| 2165 | DRM_ERROR("Got encoder index incorrect - returning 0\n")__drm_err("Got encoder index incorrect - returning 0\n"); | |||
| 2166 | return 0; | |||
| 2167 | } | |||
| 2168 | if (rdev->mode_info.active_encoders & (1 << enc_idx)) | |||
| 2169 | DRM_ERROR("chosen encoder in use %d\n", enc_idx)__drm_err("chosen encoder in use %d\n", enc_idx); | |||
| 2170 | ||||
| 2171 | rdev->mode_info.active_encoders |= (1 << enc_idx); | |||
| 2172 | return enc_idx; | |||
| 2173 | } | |||
| 2174 | ||||
| 2175 | /* This only needs to be called once at startup */ | |||
| 2176 | void | |||
| 2177 | radeon_atom_encoder_init(struct radeon_device *rdev) | |||
| 2178 | { | |||
| 2179 | struct drm_device *dev = rdev->ddev; | |||
| 2180 | struct drm_encoder *encoder; | |||
| 2181 | ||||
| 2182 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)for (encoder = ({ const __typeof( ((__typeof(*encoder) *)0)-> head ) *__mptr = ((&dev->mode_config.encoder_list)-> next); (__typeof(*encoder) *)( (char *)__mptr - __builtin_offsetof (__typeof(*encoder), head) );}); &encoder->head != (& dev->mode_config.encoder_list); encoder = ({ const __typeof ( ((__typeof(*encoder) *)0)->head ) *__mptr = (encoder-> head.next); (__typeof(*encoder) *)( (char *)__mptr - __builtin_offsetof (__typeof(*encoder), head) );})) { | |||
| 2183 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2184 | struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); | |||
| 2185 | ||||
| 2186 | switch (radeon_encoder->encoder_id) { | |||
| 2187 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 2188 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 2189 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 2190 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 2191 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 2192 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT7, 0, 0); | |||
| 2193 | break; | |||
| 2194 | default: | |||
| 2195 | break; | |||
| 2196 | } | |||
| 2197 | ||||
| 2198 | if (ext_encoder && (ASIC_IS_DCE41(rdev)((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP)) || ASIC_IS_DCE61(rdev)((rdev->family >= CHIP_ARUBA) && (rdev->flags & RADEON_IS_IGP)))) | |||
| 2199 | atombios_external_encoder_setup(encoder, ext_encoder, | |||
| 2200 | EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT0x07); | |||
| 2201 | } | |||
| 2202 | } | |||
| 2203 | ||||
| 2204 | static void | |||
| 2205 | radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | |||
| 2206 | struct drm_display_mode *mode, | |||
| 2207 | struct drm_display_mode *adjusted_mode) | |||
| 2208 | { | |||
| 2209 | struct drm_device *dev = encoder->dev; | |||
| 2210 | struct radeon_device *rdev = dev->dev_private; | |||
| 2211 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2212 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |||
| 2213 | int encoder_mode; | |||
| 2214 | ||||
| 2215 | radeon_encoder->pixel_clock = adjusted_mode->clock; | |||
| 2216 | ||||
| 2217 | /* need to call this here rather than in prepare() since we need some crtc info */ | |||
| 2218 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF3); | |||
| 2219 | ||||
| 2220 | if (ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600)) && !ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) { | |||
| 2221 | if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ) | ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )))) | |||
| 2222 | atombios_yuv_setup(encoder, true1); | |||
| 2223 | else | |||
| 2224 | atombios_yuv_setup(encoder, false0); | |||
| 2225 | } | |||
| 2226 | ||||
| 2227 | switch (radeon_encoder->encoder_id) { | |||
| 2228 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 2229 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 2230 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 2231 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 2232 | atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE1); | |||
| 2233 | break; | |||
| 2234 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 2235 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 2236 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 2237 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 2238 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 2239 | /* handled in dpms */ | |||
| 2240 | break; | |||
| 2241 | case ENCODER_OBJECT_ID_INTERNAL_DDI0x19: | |||
| 2242 | case ENCODER_OBJECT_ID_INTERNAL_DVO10x0B: | |||
| 2243 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 2244 | atombios_dvo_setup(encoder, ATOM_ENABLE1); | |||
| 2245 | break; | |||
| 2246 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 2247 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 2248 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 2249 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 2250 | atombios_dac_setup(encoder, ATOM_ENABLE1); | |||
| 2251 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )) | ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) { | |||
| 2252 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )) | ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 2253 | atombios_tv_setup(encoder, ATOM_ENABLE1); | |||
| 2254 | else | |||
| 2255 | atombios_tv_setup(encoder, ATOM_DISABLE0); | |||
| 2256 | } | |||
| 2257 | break; | |||
| 2258 | } | |||
| 2259 | ||||
| 2260 | atombios_apply_encoder_quirks(encoder, adjusted_mode); | |||
| 2261 | ||||
| 2262 | encoder_mode = atombios_get_encoder_mode(encoder); | |||
| 2263 | if (connector && (radeon_audio != 0) && | |||
| 2264 | ((encoder_mode == ATOM_ENCODER_MODE_HDMI3) || | |||
| 2265 | ENCODER_MODE_IS_DP(encoder_mode)(((encoder_mode) == 0) || ((encoder_mode) == 5)))) | |||
| 2266 | radeon_audio_mode_set(encoder, adjusted_mode); | |||
| 2267 | } | |||
| 2268 | ||||
| 2269 | static bool_Bool | |||
| 2270 | atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 2271 | { | |||
| 2272 | struct drm_device *dev = encoder->dev; | |||
| 2273 | struct radeon_device *rdev = dev->dev_private; | |||
| 2274 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2275 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 2276 | ||||
| 2277 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )) | | |||
| 2278 | ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ) | | |||
| 2279 | ATOM_DEVICE_CRT_SUPPORT((0x1L << 0x00000000 ) | (0x1L << 0x00000004 )))) { | |||
| 2280 | DAC_LOAD_DETECTION_PS_ALLOCATION args; | |||
| 2281 | int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection)(__builtin_offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, DAC_LoadDetection )/sizeof(USHORT)); | |||
| 2282 | uint8_t frev, crev; | |||
| 2283 | ||||
| 2284 | memset(&args, 0, sizeof(args))__builtin_memset((&args), (0), (sizeof(args))); | |||
| 2285 | ||||
| 2286 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |||
| 2287 | return false0; | |||
| 2288 | ||||
| 2289 | args.sDacload.ucMisc = 0; | |||
| 2290 | ||||
| 2291 | if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC10x04) || | |||
| 2292 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15)) | |||
| 2293 | args.sDacload.ucDacType = ATOM_DAC_A0; | |||
| 2294 | else | |||
| 2295 | args.sDacload.ucDacType = ATOM_DAC_B1; | |||
| 2296 | ||||
| 2297 | if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT(0x1L << 0x00000000 )) | |||
| 2298 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT)((__uint16_t)((0x1L << 0x00000000 ))); | |||
| 2299 | else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT(0x1L << 0x00000004 )) | |||
| 2300 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT)((__uint16_t)((0x1L << 0x00000004 ))); | |||
| 2301 | else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 )) { | |||
| 2302 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT)((__uint16_t)((0x1L << 0x00000008 ))); | |||
| 2303 | if (crev >= 3) | |||
| 2304 | args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb0x01; | |||
| 2305 | } else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT(0x1L << 0x00000002 )) { | |||
| 2306 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT)((__uint16_t)((0x1L << 0x00000002 ))); | |||
| 2307 | if (crev >= 3) | |||
| 2308 | args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb0x01; | |||
| 2309 | } | |||
| 2310 | ||||
| 2311 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | |||
| 2312 | ||||
| 2313 | return true1; | |||
| 2314 | } else | |||
| 2315 | return false0; | |||
| 2316 | } | |||
| 2317 | ||||
| 2318 | static enum drm_connector_status | |||
| 2319 | radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 2320 | { | |||
| 2321 | struct drm_device *dev = encoder->dev; | |||
| 2322 | struct radeon_device *rdev = dev->dev_private; | |||
| 2323 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2324 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 2325 | uint32_t bios_0_scratch; | |||
| 2326 | ||||
| 2327 | if (!atombios_dac_load_detect(encoder, connector)) { | |||
| 2328 | DRM_DEBUG_KMS("detect returned false \n")___drm_dbg(((void *)0), DRM_UT_KMS, "detect returned false \n" ); | |||
| 2329 | return connector_status_unknown; | |||
| 2330 | } | |||
| 2331 | ||||
| 2332 | if (rdev->family >= CHIP_R600) | |||
| 2333 | bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH)r100_mm_rreg(rdev, (0x1724), 0); | |||
| 2334 | else | |||
| 2335 | bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH)r100_mm_rreg(rdev, (0x0010), 0); | |||
| 2336 | ||||
| 2337 | DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices)___drm_dbg(((void *)0), DRM_UT_KMS, "Bios 0 scratch %x %08x\n" , bios_0_scratch, radeon_encoder->devices); | |||
| 2338 | if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT(0x1L << 0x00000000 )) { | |||
| 2339 | if (bios_0_scratch & ATOM_S0_CRT1_MASK(0x00000001L +0x00000002L)) | |||
| 2340 | return connector_status_connected; | |||
| 2341 | } | |||
| 2342 | if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT(0x1L << 0x00000004 )) { | |||
| 2343 | if (bios_0_scratch & ATOM_S0_CRT2_MASK(0x00000100L +0x00000200L)) | |||
| 2344 | return connector_status_connected; | |||
| 2345 | } | |||
| 2346 | if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 )) { | |||
| 2347 | if (bios_0_scratch & (ATOM_S0_CV_MASK(0x00001000L +0x00002000L)|ATOM_S0_CV_MASK_A(0x00000010L +0x00000020L))) | |||
| 2348 | return connector_status_connected; | |||
| 2349 | } | |||
| 2350 | if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT(0x1L << 0x00000002 )) { | |||
| 2351 | if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE0x00000400L | ATOM_S0_TV1_COMPOSITE_A0x00000004L)) | |||
| 2352 | return connector_status_connected; /* CTV */ | |||
| 2353 | else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO0x00000800L | ATOM_S0_TV1_SVIDEO_A0x00000008L)) | |||
| 2354 | return connector_status_connected; /* STV */ | |||
| 2355 | } | |||
| 2356 | return connector_status_disconnected; | |||
| 2357 | } | |||
| 2358 | ||||
| 2359 | static enum drm_connector_status | |||
| 2360 | radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 2361 | { | |||
| 2362 | struct drm_device *dev = encoder->dev; | |||
| 2363 | struct radeon_device *rdev = dev->dev_private; | |||
| 2364 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2365 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 2366 | struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); | |||
| 2367 | u32 bios_0_scratch; | |||
| 2368 | ||||
| 2369 | if (!ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) | |||
| 2370 | return connector_status_unknown; | |||
| 2371 | ||||
| 2372 | if (!ext_encoder) | |||
| 2373 | return connector_status_unknown; | |||
| 2374 | ||||
| 2375 | if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT((0x1L << 0x00000000 ) | (0x1L << 0x00000004 ))) == 0) | |||
| 2376 | return connector_status_unknown; | |||
| 2377 | ||||
| 2378 | /* load detect on the dp bridge */ | |||
| 2379 | atombios_external_encoder_setup(encoder, ext_encoder, | |||
| 2380 | EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION0x12); | |||
| 2381 | ||||
| 2382 | bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH)r100_mm_rreg(rdev, (0x1724), 0); | |||
| 2383 | ||||
| 2384 | DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices)___drm_dbg(((void *)0), DRM_UT_KMS, "Bios 0 scratch %x %08x\n" , bios_0_scratch, radeon_encoder->devices); | |||
| 2385 | if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT(0x1L << 0x00000000 )) { | |||
| 2386 | if (bios_0_scratch & ATOM_S0_CRT1_MASK(0x00000001L +0x00000002L)) | |||
| 2387 | return connector_status_connected; | |||
| 2388 | } | |||
| 2389 | if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT(0x1L << 0x00000004 )) { | |||
| 2390 | if (bios_0_scratch & ATOM_S0_CRT2_MASK(0x00000100L +0x00000200L)) | |||
| 2391 | return connector_status_connected; | |||
| 2392 | } | |||
| 2393 | if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 )) { | |||
| 2394 | if (bios_0_scratch & (ATOM_S0_CV_MASK(0x00001000L +0x00002000L)|ATOM_S0_CV_MASK_A(0x00000010L +0x00000020L))) | |||
| 2395 | return connector_status_connected; | |||
| 2396 | } | |||
| 2397 | if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT(0x1L << 0x00000002 )) { | |||
| 2398 | if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE0x00000400L | ATOM_S0_TV1_COMPOSITE_A0x00000004L)) | |||
| 2399 | return connector_status_connected; /* CTV */ | |||
| 2400 | else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO0x00000800L | ATOM_S0_TV1_SVIDEO_A0x00000008L)) | |||
| 2401 | return connector_status_connected; /* STV */ | |||
| 2402 | } | |||
| 2403 | return connector_status_disconnected; | |||
| 2404 | } | |||
| 2405 | ||||
| 2406 | void | |||
| 2407 | radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) | |||
| 2408 | { | |||
| 2409 | struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); | |||
| 2410 | ||||
| 2411 | if (ext_encoder) | |||
| 2412 | /* ddc_setup on the dp bridge */ | |||
| 2413 | atombios_external_encoder_setup(encoder, ext_encoder, | |||
| 2414 | EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP0x14); | |||
| 2415 | ||||
| 2416 | } | |||
| 2417 | ||||
| 2418 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | |||
| 2419 | { | |||
| 2420 | struct radeon_device *rdev = encoder->dev->dev_private; | |||
| 2421 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2422 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | |||
| 2423 | ||||
| 2424 | if ((radeon_encoder->active_device & | |||
| 2425 | (ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 )) | ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) || | |||
| 2426 | (radeon_encoder_get_dp_bridge_encoder_id(encoder) != | |||
| 2427 | ENCODER_OBJECT_ID_NONE0x00)) { | |||
| 2428 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | |||
| 2429 | if (dig) { | |||
| 2430 | if (dig->dig_encoder >= 0) | |||
| 2431 | radeon_atom_release_dig_encoder(rdev, dig->dig_encoder); | |||
| 2432 | dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1); | |||
| 2433 | if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT((0x1L << 0x00000003 ) | (0x1L << 0x00000007 ) | ( 0x1L << 0x00000009 ) | (0x1L << 0x0000000A ) | (0x1L << 0x0000000B ) | (0x1L << 0x00000006 ))) { | |||
| 2434 | if (rdev->family >= CHIP_R600) | |||
| 2435 | dig->afmt = rdev->mode_info.afmt[dig->dig_encoder]; | |||
| 2436 | else | |||
| 2437 | /* RS600/690/740 have only 1 afmt block */ | |||
| 2438 | dig->afmt = rdev->mode_info.afmt[0]; | |||
| 2439 | } | |||
| 2440 | } | |||
| 2441 | } | |||
| 2442 | ||||
| 2443 | radeon_atom_output_lock(encoder, true1); | |||
| 2444 | ||||
| 2445 | if (connector) { | |||
| 2446 | struct radeon_connector *radeon_connector = to_radeon_connector(connector)({ const __typeof( ((struct radeon_connector *)0)->base ) * __mptr = (connector); (struct radeon_connector *)( (char *)__mptr - __builtin_offsetof(struct radeon_connector, base) );}); | |||
| 2447 | ||||
| 2448 | /* select the clock/data port if it uses a router */ | |||
| 2449 | if (radeon_connector->router.cd_valid) | |||
| 2450 | radeon_router_select_cd_port(radeon_connector); | |||
| 2451 | ||||
| 2452 | /* turn eDP panel on for mode set */ | |||
| 2453 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP14) | |||
| 2454 | atombios_set_edp_panel_power(connector, | |||
| 2455 | ATOM_TRANSMITTER_ACTION_POWER_ON12); | |||
| 2456 | } | |||
| 2457 | ||||
| 2458 | /* this is needed for the pll/ss setup to work correctly in some cases */ | |||
| 2459 | atombios_set_encoder_crtc_source(encoder); | |||
| 2460 | /* set up the FMT blocks */ | |||
| 2461 | if (ASIC_IS_DCE8(rdev)((rdev->family >= CHIP_BONAIRE))) | |||
| 2462 | dce8_program_fmt(encoder); | |||
| 2463 | else if (ASIC_IS_DCE4(rdev)((rdev->family >= CHIP_CEDAR))) | |||
| 2464 | dce4_program_fmt(encoder); | |||
| 2465 | else if (ASIC_IS_DCE3(rdev)((rdev->family >= CHIP_RV620))) | |||
| 2466 | dce3_program_fmt(encoder); | |||
| 2467 | else if (ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600))) | |||
| 2468 | avivo_program_fmt(encoder); | |||
| 2469 | } | |||
| 2470 | ||||
| 2471 | static void radeon_atom_encoder_commit(struct drm_encoder *encoder) | |||
| 2472 | { | |||
| 2473 | /* need to call this here as we need the crtc set up */ | |||
| 2474 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON0); | |||
| 2475 | radeon_atom_output_lock(encoder, false0); | |||
| 2476 | } | |||
| 2477 | ||||
| 2478 | static void radeon_atom_encoder_disable(struct drm_encoder *encoder) | |||
| 2479 | { | |||
| 2480 | struct drm_device *dev = encoder->dev; | |||
| 2481 | struct radeon_device *rdev = dev->dev_private; | |||
| 2482 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2483 | struct radeon_encoder_atom_dig *dig; | |||
| 2484 | ||||
| 2485 | /* check for pre-DCE3 cards with shared encoders; | |||
| 2486 | * can't really use the links individually, so don't disable | |||
| 2487 | * the encoder if it's in use by another connector | |||
| 2488 | */ | |||
| 2489 | if (!ASIC_IS_DCE3(rdev)((rdev->family >= CHIP_RV620))) { | |||
| 2490 | struct drm_encoder *other_encoder; | |||
| 2491 | struct radeon_encoder *other_radeon_encoder; | |||
| 2492 | ||||
| 2493 | list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head)for (other_encoder = ({ const __typeof( ((__typeof(*other_encoder ) *)0)->head ) *__mptr = ((&dev->mode_config.encoder_list )->next); (__typeof(*other_encoder) *)( (char *)__mptr - __builtin_offsetof (__typeof(*other_encoder), head) );}); &other_encoder-> head != (&dev->mode_config.encoder_list); other_encoder = ({ const __typeof( ((__typeof(*other_encoder) *)0)->head ) *__mptr = (other_encoder->head.next); (__typeof(*other_encoder ) *)( (char *)__mptr - __builtin_offsetof(__typeof(*other_encoder ), head) );})) { | |||
| 2494 | other_radeon_encoder = to_radeon_encoder(other_encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (other_encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof(struct radeon_encoder, base) );}); | |||
| 2495 | if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && | |||
| 2496 | drm_helper_encoder_in_use(other_encoder)) | |||
| 2497 | goto disable_done; | |||
| 2498 | } | |||
| 2499 | } | |||
| 2500 | ||||
| 2501 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF3); | |||
| 2502 | ||||
| 2503 | switch (radeon_encoder->encoder_id) { | |||
| 2504 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 2505 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 2506 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 2507 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 2508 | atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_DISABLE0); | |||
| 2509 | break; | |||
| 2510 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 2511 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 2512 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 2513 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 2514 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 2515 | /* handled in dpms */ | |||
| 2516 | break; | |||
| 2517 | case ENCODER_OBJECT_ID_INTERNAL_DDI0x19: | |||
| 2518 | case ENCODER_OBJECT_ID_INTERNAL_DVO10x0B: | |||
| 2519 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 2520 | atombios_dvo_setup(encoder, ATOM_DISABLE0); | |||
| 2521 | break; | |||
| 2522 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 2523 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 2524 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 2525 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 2526 | atombios_dac_setup(encoder, ATOM_DISABLE0); | |||
| 2527 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT((0x1L << 0x00000002 )) | ATOM_DEVICE_CV_SUPPORT(0x1L << 0x00000008 ))) | |||
| 2528 | atombios_tv_setup(encoder, ATOM_DISABLE0); | |||
| 2529 | break; | |||
| 2530 | } | |||
| 2531 | ||||
| 2532 | disable_done: | |||
| 2533 | if (radeon_encoder_is_digital(encoder)) { | |||
| 2534 | if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI3) { | |||
| 2535 | if (rdev->asic->display.hdmi_enable) | |||
| 2536 | radeon_hdmi_enable(rdev, encoder, false)(rdev)->asic->display.hdmi_enable((encoder), (0)); | |||
| 2537 | } | |||
| 2538 | if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST5) { | |||
| 2539 | dig = radeon_encoder->enc_priv; | |||
| 2540 | radeon_atom_release_dig_encoder(rdev, dig->dig_encoder); | |||
| 2541 | dig->dig_encoder = -1; | |||
| 2542 | radeon_encoder->active_device = 0; | |||
| 2543 | } | |||
| 2544 | } else | |||
| 2545 | radeon_encoder->active_device = 0; | |||
| 2546 | } | |||
| 2547 | ||||
| 2548 | /* these are handled by the primary encoders */ | |||
| 2549 | static void radeon_atom_ext_prepare(struct drm_encoder *encoder) | |||
| 2550 | { | |||
| 2551 | ||||
| 2552 | } | |||
| 2553 | ||||
| 2554 | static void radeon_atom_ext_commit(struct drm_encoder *encoder) | |||
| 2555 | { | |||
| 2556 | ||||
| 2557 | } | |||
| 2558 | ||||
| 2559 | static void | |||
| 2560 | radeon_atom_ext_mode_set(struct drm_encoder *encoder, | |||
| 2561 | struct drm_display_mode *mode, | |||
| 2562 | struct drm_display_mode *adjusted_mode) | |||
| 2563 | { | |||
| 2564 | ||||
| 2565 | } | |||
| 2566 | ||||
| 2567 | static void radeon_atom_ext_disable(struct drm_encoder *encoder) | |||
| 2568 | { | |||
| 2569 | ||||
| 2570 | } | |||
| 2571 | ||||
| 2572 | static void | |||
| 2573 | radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) | |||
| 2574 | { | |||
| 2575 | ||||
| 2576 | } | |||
| 2577 | ||||
| 2578 | static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { | |||
| 2579 | .dpms = radeon_atom_ext_dpms, | |||
| 2580 | .prepare = radeon_atom_ext_prepare, | |||
| 2581 | .mode_set = radeon_atom_ext_mode_set, | |||
| 2582 | .commit = radeon_atom_ext_commit, | |||
| 2583 | .disable = radeon_atom_ext_disable, | |||
| 2584 | /* no detect for TMDS/LVDS yet */ | |||
| 2585 | }; | |||
| 2586 | ||||
| 2587 | static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { | |||
| 2588 | .dpms = radeon_atom_encoder_dpms, | |||
| 2589 | .mode_fixup = radeon_atom_mode_fixup, | |||
| 2590 | .prepare = radeon_atom_encoder_prepare, | |||
| 2591 | .mode_set = radeon_atom_encoder_mode_set, | |||
| 2592 | .commit = radeon_atom_encoder_commit, | |||
| 2593 | .disable = radeon_atom_encoder_disable, | |||
| 2594 | .detect = radeon_atom_dig_detect, | |||
| 2595 | }; | |||
| 2596 | ||||
| 2597 | static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { | |||
| 2598 | .dpms = radeon_atom_encoder_dpms, | |||
| 2599 | .mode_fixup = radeon_atom_mode_fixup, | |||
| 2600 | .prepare = radeon_atom_encoder_prepare, | |||
| 2601 | .mode_set = radeon_atom_encoder_mode_set, | |||
| 2602 | .commit = radeon_atom_encoder_commit, | |||
| 2603 | .detect = radeon_atom_dac_detect, | |||
| 2604 | }; | |||
| 2605 | ||||
| 2606 | void radeon_enc_destroy(struct drm_encoder *encoder) | |||
| 2607 | { | |||
| 2608 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2609 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) | |||
| 2610 | radeon_atom_backlight_exit(radeon_encoder); | |||
| 2611 | kfree(radeon_encoder->enc_priv); | |||
| 2612 | drm_encoder_cleanup(encoder); | |||
| 2613 | kfree(radeon_encoder); | |||
| 2614 | } | |||
| 2615 | ||||
| 2616 | static const struct drm_encoder_funcs radeon_atom_enc_funcs = { | |||
| 2617 | .destroy = radeon_enc_destroy, | |||
| 2618 | }; | |||
| 2619 | ||||
| 2620 | static struct radeon_encoder_atom_dac * | |||
| 2621 | radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) | |||
| 2622 | { | |||
| 2623 | struct drm_device *dev = radeon_encoder->base.dev; | |||
| 2624 | struct radeon_device *rdev = dev->dev_private; | |||
| 2625 | struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL(0x0001 | 0x0004)); | |||
| 2626 | ||||
| 2627 | if (!dac) | |||
| 2628 | return NULL((void *)0); | |||
| 2629 | ||||
| 2630 | dac->tv_std = radeon_atombios_get_tv_info(rdev); | |||
| 2631 | return dac; | |||
| 2632 | } | |||
| 2633 | ||||
| 2634 | static struct radeon_encoder_atom_dig * | |||
| 2635 | radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) | |||
| 2636 | { | |||
| 2637 | int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK0x0700) >> ENUM_ID_SHIFT0x08; | |||
| 2638 | struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL(0x0001 | 0x0004)); | |||
| 2639 | ||||
| 2640 | if (!dig) | |||
| 2641 | return NULL((void *)0); | |||
| 2642 | ||||
| 2643 | /* coherent mode by default */ | |||
| 2644 | dig->coherent_mode = true1; | |||
| 2645 | dig->dig_encoder = -1; | |||
| 2646 | ||||
| 2647 | if (encoder_enum == 2) | |||
| 2648 | dig->linkb = true1; | |||
| 2649 | else | |||
| 2650 | dig->linkb = false0; | |||
| 2651 | ||||
| 2652 | return dig; | |||
| 2653 | } | |||
| 2654 | ||||
| 2655 | void | |||
| 2656 | radeon_add_atom_encoder(struct drm_device *dev, | |||
| 2657 | uint32_t encoder_enum, | |||
| 2658 | uint32_t supported_device, | |||
| 2659 | u16 caps) | |||
| 2660 | { | |||
| 2661 | struct radeon_device *rdev = dev->dev_private; | |||
| 2662 | struct drm_encoder *encoder; | |||
| 2663 | struct radeon_encoder *radeon_encoder; | |||
| 2664 | ||||
| 2665 | /* see if we already added it */ | |||
| 2666 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)for (encoder = ({ const __typeof( ((__typeof(*encoder) *)0)-> head ) *__mptr = ((&dev->mode_config.encoder_list)-> next); (__typeof(*encoder) *)( (char *)__mptr - __builtin_offsetof (__typeof(*encoder), head) );}); &encoder->head != (& dev->mode_config.encoder_list); encoder = ({ const __typeof ( ((__typeof(*encoder) *)0)->head ) *__mptr = (encoder-> head.next); (__typeof(*encoder) *)( (char *)__mptr - __builtin_offsetof (__typeof(*encoder), head) );})) { | |||
| ||||
| 2667 | radeon_encoder = to_radeon_encoder(encoder)({ const __typeof( ((struct radeon_encoder *)0)->base ) *__mptr = (encoder); (struct radeon_encoder *)( (char *)__mptr - __builtin_offsetof (struct radeon_encoder, base) );}); | |||
| 2668 | if (radeon_encoder->encoder_enum == encoder_enum) { | |||
| 2669 | radeon_encoder->devices |= supported_device; | |||
| 2670 | return; | |||
| 2671 | } | |||
| 2672 | ||||
| 2673 | } | |||
| 2674 | ||||
| 2675 | /* add a new one */ | |||
| 2676 | radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL(0x0001 | 0x0004)); | |||
| 2677 | if (!radeon_encoder) | |||
| 2678 | return; | |||
| 2679 | ||||
| 2680 | encoder = &radeon_encoder->base; | |||
| 2681 | switch (rdev->num_crtc) { | |||
| 2682 | case 1: | |||
| 2683 | encoder->possible_crtcs = 0x1; | |||
| 2684 | break; | |||
| 2685 | case 2: | |||
| 2686 | default: | |||
| 2687 | encoder->possible_crtcs = 0x3; | |||
| 2688 | break; | |||
| 2689 | case 4: | |||
| 2690 | encoder->possible_crtcs = 0xf; | |||
| 2691 | break; | |||
| 2692 | case 6: | |||
| 2693 | encoder->possible_crtcs = 0x3f; | |||
| 2694 | break; | |||
| 2695 | } | |||
| 2696 | ||||
| 2697 | radeon_encoder->enc_priv = NULL((void *)0); | |||
| 2698 | ||||
| 2699 | radeon_encoder->encoder_enum = encoder_enum; | |||
| 2700 | radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK0x00FF) >> OBJECT_ID_SHIFT0x00; | |||
| 2701 | radeon_encoder->devices = supported_device; | |||
| 2702 | radeon_encoder->rmx_type = RMX_OFF; | |||
| 2703 | radeon_encoder->underscan_type = UNDERSCAN_OFF; | |||
| 2704 | radeon_encoder->is_ext_encoder = false0; | |||
| 2705 | radeon_encoder->caps = caps; | |||
| 2706 | ||||
| 2707 | switch (radeon_encoder->encoder_id) { | |||
| 2708 | case ENCODER_OBJECT_ID_INTERNAL_LVDS0x01: | |||
| 2709 | case ENCODER_OBJECT_ID_INTERNAL_TMDS10x02: | |||
| 2710 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS10x13: | |||
| 2711 | case ENCODER_OBJECT_ID_INTERNAL_LVTM10x0F: | |||
| 2712 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 2713 | radeon_encoder->rmx_type = RMX_FULL; | |||
| 2714 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2715 | DRM_MODE_ENCODER_LVDS3, NULL((void *)0)); | |||
| 2716 | radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); | |||
| 2717 | } else { | |||
| 2718 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2719 | DRM_MODE_ENCODER_TMDS2, NULL((void *)0)); | |||
| 2720 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | |||
| 2721 | } | |||
| 2722 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | |||
| 2723 | break; | |||
| 2724 | case ENCODER_OBJECT_ID_INTERNAL_DAC10x04: | |||
| 2725 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2726 | DRM_MODE_ENCODER_DAC1, NULL((void *)0)); | |||
| 2727 | radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); | |||
| 2728 | drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); | |||
| 2729 | break; | |||
| 2730 | case ENCODER_OBJECT_ID_INTERNAL_DAC20x05: | |||
| 2731 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC10x15: | |||
| 2732 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC20x16: | |||
| 2733 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2734 | DRM_MODE_ENCODER_TVDAC4, NULL((void *)0)); | |||
| 2735 | radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); | |||
| 2736 | drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); | |||
| 2737 | break; | |||
| 2738 | case ENCODER_OBJECT_ID_INTERNAL_DVO10x0B: | |||
| 2739 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO10x14: | |||
| 2740 | case ENCODER_OBJECT_ID_INTERNAL_DDI0x19: | |||
| 2741 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY0x1E: | |||
| 2742 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA0x1F: | |||
| 2743 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY10x20: | |||
| 2744 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY20x21: | |||
| 2745 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY30x25: | |||
| 2746 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) { | |||
| 2747 | radeon_encoder->rmx_type = RMX_FULL; | |||
| 2748 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2749 | DRM_MODE_ENCODER_LVDS3, NULL((void *)0)); | |||
| 2750 | radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); | |||
| 2751 | } else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT((0x1L << 0x00000000 ) | (0x1L << 0x00000004 )))) { | |||
| 2752 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2753 | DRM_MODE_ENCODER_DAC1, NULL((void *)0)); | |||
| 2754 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | |||
| 2755 | } else { | |||
| 2756 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2757 | DRM_MODE_ENCODER_TMDS2, NULL((void *)0)); | |||
| 2758 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | |||
| 2759 | } | |||
| 2760 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | |||
| 2761 | break; | |||
| 2762 | case ENCODER_OBJECT_ID_SI170B0x08: | |||
| 2763 | case ENCODER_OBJECT_ID_CH73030x09: | |||
| 2764 | case ENCODER_OBJECT_ID_EXTERNAL_SDVOA0x0C: | |||
| 2765 | case ENCODER_OBJECT_ID_EXTERNAL_SDVOB0x0D: | |||
| 2766 | case ENCODER_OBJECT_ID_TITFP5130x0E: | |||
| 2767 | case ENCODER_OBJECT_ID_VT16230x10: | |||
| 2768 | case ENCODER_OBJECT_ID_HDMI_SI19300x11: | |||
| 2769 | case ENCODER_OBJECT_ID_TRAVIS0x23: | |||
| 2770 | case ENCODER_OBJECT_ID_NUTMEG0x22: | |||
| 2771 | /* these are handled by the primary encoders */ | |||
| 2772 | radeon_encoder->is_ext_encoder = true1; | |||
| 2773 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT((0x1L << 0x00000001 ) | (0x1L << 0x00000005 )))) | |||
| 2774 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2775 | DRM_MODE_ENCODER_LVDS3, NULL((void *)0)); | |||
| 2776 | else if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT((0x1L << 0x00000000 ) | (0x1L << 0x00000004 )))) | |||
| 2777 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2778 | DRM_MODE_ENCODER_DAC1, NULL((void *)0)); | |||
| 2779 | else | |||
| 2780 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, | |||
| 2781 | DRM_MODE_ENCODER_TMDS2, NULL((void *)0)); | |||
| 2782 | drm_encoder_helper_add(encoder, &radeon_atom_ext_helper_funcs); | |||
| 2783 | break; | |||
| 2784 | } | |||
| 2785 | } | |||
|
| 1 | /* Public domain. */ |
| 2 | |
| 3 | #ifndef _LINUX_SLAB_H |
| 4 | #define _LINUX_SLAB_H |
| 5 | |
| 6 | #include <sys/types.h> |
| 7 | #include <sys/malloc.h> |
| 8 | |
| 9 | #include <linux/types.h> |
| 10 | #include <linux/workqueue.h> |
| 11 | #include <linux/gfp.h> |
| 12 | |
| 13 | #include <linux/processor.h> /* for CACHELINESIZE */ |
| 14 | |
| 15 | #define ARCH_KMALLOC_MINALIGN64 CACHELINESIZE64 |
| 16 | |
| 17 | #define ZERO_SIZE_PTR((void *)0) NULL((void *)0) |
| 18 | |
| 19 | static inline void * |
| 20 | kmalloc(size_t size, int flags) |
| 21 | { |
| 22 | return malloc(size, M_DRM145, flags); |
| 23 | } |
| 24 | |
| 25 | static inline void * |
| 26 | kmalloc_array(size_t n, size_t size, int flags) |
| 27 | { |
| 28 | if (n != 0 && SIZE_MAX0xffffffffffffffffUL / n < size) |
| 29 | return NULL((void *)0); |
| 30 | return malloc(n * size, M_DRM145, flags); |
| 31 | } |
| 32 | |
| 33 | static inline void * |
| 34 | kcalloc(size_t n, size_t size, int flags) |
| 35 | { |
| 36 | if (n != 0 && SIZE_MAX0xffffffffffffffffUL / n < size) |
| 37 | return NULL((void *)0); |
| 38 | return malloc(n * size, M_DRM145, flags | M_ZERO0x0008); |
| 39 | } |
| 40 | |
| 41 | static inline void * |
| 42 | kzalloc(size_t size, int flags) |
| 43 | { |
| 44 | return malloc(size, M_DRM145, flags | M_ZERO0x0008); |
| 45 | } |
| 46 | |
| 47 | static inline void |
| 48 | kfree(const void *objp) |
| 49 | { |
| 50 | free((void *)objp, M_DRM145, 0); |
| 51 | } |
| 52 | |
| 53 | #endif |