1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2007-8 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * 5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 6254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 7254885Sdumbbell * to deal in the Software without restriction, including without limitation 8254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 10254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 11254885Sdumbbell * 12254885Sdumbbell * The above copyright notice and this permission notice shall be included in 13254885Sdumbbell * all copies or substantial portions of the Software. 14254885Sdumbbell * 15254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 22254885Sdumbbell * 23254885Sdumbbell * Authors: Dave Airlie 24254885Sdumbbell * Alex Deucher 25254885Sdumbbell */ 26254885Sdumbbell 27254885Sdumbbell#include <sys/cdefs.h> 28254885Sdumbbell__FBSDID("$FreeBSD$"); 29254885Sdumbbell 30254885Sdumbbell#include <dev/drm2/drmP.h> 31254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h> 32254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h> 33254885Sdumbbell#include "radeon.h" 34254885Sdumbbell#include "radeon_asic.h" 35254885Sdumbbell#include "atom.h" 36254885Sdumbbell 37254885Sdumbbellstatic void radeon_legacy_encoder_disable(struct drm_encoder *encoder) 38254885Sdumbbell{ 39254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 40254885Sdumbbell struct drm_encoder_helper_funcs *encoder_funcs; 41254885Sdumbbell 42254885Sdumbbell encoder_funcs = encoder->helper_private; 43254885Sdumbbell encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); 44254885Sdumbbell radeon_encoder->active_device = 0; 45254885Sdumbbell} 46254885Sdumbbell 47254885Sdumbbellstatic void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) 48254885Sdumbbell{ 49254885Sdumbbell struct drm_device *dev = encoder->dev; 50254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 51254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 52254885Sdumbbell uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; 53254885Sdumbbell int panel_pwr_delay = 2000; 54254885Sdumbbell bool is_mac = false; 55254885Sdumbbell uint8_t backlight_level; 56254885Sdumbbell DRM_DEBUG_KMS("\n"); 57254885Sdumbbell 58254885Sdumbbell lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); 59254885Sdumbbell backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; 60254885Sdumbbell 61254885Sdumbbell if (radeon_encoder->enc_priv) { 62254885Sdumbbell if (rdev->is_atom_bios) { 63254885Sdumbbell struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; 64254885Sdumbbell panel_pwr_delay = lvds->panel_pwr_delay; 65254885Sdumbbell if (lvds->bl_dev) 66254885Sdumbbell backlight_level = lvds->backlight_level; 67254885Sdumbbell } else { 68254885Sdumbbell struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; 69254885Sdumbbell panel_pwr_delay = lvds->panel_pwr_delay; 70254885Sdumbbell if (lvds->bl_dev) 71254885Sdumbbell backlight_level = lvds->backlight_level; 72254885Sdumbbell } 73254885Sdumbbell } 74254885Sdumbbell 75254885Sdumbbell /* macs (and possibly some x86 oem systems?) wire up LVDS strangely 76254885Sdumbbell * Taken from radeonfb. 77254885Sdumbbell */ 78254885Sdumbbell if ((rdev->mode_info.connector_table == CT_IBOOK) || 79254885Sdumbbell (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) || 80254885Sdumbbell (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) || 81254885Sdumbbell (rdev->mode_info.connector_table == CT_POWERBOOK_VGA)) 82254885Sdumbbell is_mac = true; 83254885Sdumbbell 84254885Sdumbbell switch (mode) { 85254885Sdumbbell case DRM_MODE_DPMS_ON: 86254885Sdumbbell disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN); 87254885Sdumbbell disp_pwr_man |= RADEON_AUTO_PWRUP_EN; 88254885Sdumbbell WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man); 89254885Sdumbbell lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); 90254885Sdumbbell lvds_pll_cntl |= RADEON_LVDS_PLL_EN; 91254885Sdumbbell WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); 92280183Sdumbbell mdelay(1); 93254885Sdumbbell 94254885Sdumbbell lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); 95254885Sdumbbell lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; 96254885Sdumbbell WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); 97254885Sdumbbell 98254885Sdumbbell lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS | 99254885Sdumbbell RADEON_LVDS_BL_MOD_LEVEL_MASK); 100254885Sdumbbell lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | 101254885Sdumbbell RADEON_LVDS_DIGON | RADEON_LVDS_BLON | 102254885Sdumbbell (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT)); 103254885Sdumbbell if (is_mac) 104254885Sdumbbell lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; 105280183Sdumbbell mdelay(panel_pwr_delay); 106254885Sdumbbell WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 107254885Sdumbbell break; 108254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 109254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 110254885Sdumbbell case DRM_MODE_DPMS_OFF: 111254885Sdumbbell pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); 112254885Sdumbbell WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); 113254885Sdumbbell lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; 114254885Sdumbbell if (is_mac) { 115254885Sdumbbell lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; 116254885Sdumbbell WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 117254885Sdumbbell lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); 118254885Sdumbbell } else { 119254885Sdumbbell WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 120254885Sdumbbell lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); 121254885Sdumbbell } 122280183Sdumbbell mdelay(panel_pwr_delay); 123254885Sdumbbell WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 124254885Sdumbbell WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); 125280183Sdumbbell mdelay(panel_pwr_delay); 126254885Sdumbbell break; 127254885Sdumbbell } 128254885Sdumbbell 129254885Sdumbbell if (rdev->is_atom_bios) 130254885Sdumbbell radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 131254885Sdumbbell else 132254885Sdumbbell radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 133254885Sdumbbell 134254885Sdumbbell} 135254885Sdumbbell 136254885Sdumbbellstatic void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) 137254885Sdumbbell{ 138254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 139254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 140254885Sdumbbell DRM_DEBUG("\n"); 141254885Sdumbbell 142254885Sdumbbell if (radeon_encoder->enc_priv) { 143254885Sdumbbell if (rdev->is_atom_bios) { 144254885Sdumbbell struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; 145254885Sdumbbell lvds->dpms_mode = mode; 146254885Sdumbbell } else { 147254885Sdumbbell struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; 148254885Sdumbbell lvds->dpms_mode = mode; 149254885Sdumbbell } 150254885Sdumbbell } 151254885Sdumbbell 152254885Sdumbbell radeon_legacy_lvds_update(encoder, mode); 153254885Sdumbbell} 154254885Sdumbbell 155254885Sdumbbellstatic void radeon_legacy_lvds_prepare(struct drm_encoder *encoder) 156254885Sdumbbell{ 157254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 158254885Sdumbbell 159254885Sdumbbell if (rdev->is_atom_bios) 160254885Sdumbbell radeon_atom_output_lock(encoder, true); 161254885Sdumbbell else 162254885Sdumbbell radeon_combios_output_lock(encoder, true); 163254885Sdumbbell radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF); 164254885Sdumbbell} 165254885Sdumbbell 166254885Sdumbbellstatic void radeon_legacy_lvds_commit(struct drm_encoder *encoder) 167254885Sdumbbell{ 168254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 169254885Sdumbbell 170254885Sdumbbell radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON); 171254885Sdumbbell if (rdev->is_atom_bios) 172254885Sdumbbell radeon_atom_output_lock(encoder, false); 173254885Sdumbbell else 174254885Sdumbbell radeon_combios_output_lock(encoder, false); 175254885Sdumbbell} 176254885Sdumbbell 177254885Sdumbbellstatic void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, 178254885Sdumbbell struct drm_display_mode *mode, 179254885Sdumbbell struct drm_display_mode *adjusted_mode) 180254885Sdumbbell{ 181254885Sdumbbell struct drm_device *dev = encoder->dev; 182254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 183254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 184254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 185254885Sdumbbell uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl; 186254885Sdumbbell 187254885Sdumbbell DRM_DEBUG_KMS("\n"); 188254885Sdumbbell 189254885Sdumbbell lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); 190254885Sdumbbell lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; 191254885Sdumbbell 192254885Sdumbbell lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL); 193254885Sdumbbell if (rdev->is_atom_bios) { 194254885Sdumbbell /* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl 195254885Sdumbbell * need to call that on resume to set up the reg properly. 196254885Sdumbbell */ 197254885Sdumbbell radeon_encoder->pixel_clock = adjusted_mode->clock; 198254885Sdumbbell atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); 199254885Sdumbbell lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); 200254885Sdumbbell } else { 201254885Sdumbbell struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; 202254885Sdumbbell if (lvds) { 203254885Sdumbbell DRM_DEBUG_KMS("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl); 204254885Sdumbbell lvds_gen_cntl = lvds->lvds_gen_cntl; 205254885Sdumbbell lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) | 206254885Sdumbbell (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); 207254885Sdumbbell lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) | 208254885Sdumbbell (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); 209254885Sdumbbell } else 210254885Sdumbbell lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); 211254885Sdumbbell } 212254885Sdumbbell lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; 213254885Sdumbbell lvds_gen_cntl &= ~(RADEON_LVDS_ON | 214254885Sdumbbell RADEON_LVDS_BLON | 215254885Sdumbbell RADEON_LVDS_EN | 216254885Sdumbbell RADEON_LVDS_RST_FM); 217254885Sdumbbell 218254885Sdumbbell if (ASIC_IS_R300(rdev)) 219254885Sdumbbell lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); 220254885Sdumbbell 221254885Sdumbbell if (radeon_crtc->crtc_id == 0) { 222254885Sdumbbell if (ASIC_IS_R300(rdev)) { 223254885Sdumbbell if (radeon_encoder->rmx_type != RMX_OFF) 224254885Sdumbbell lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; 225254885Sdumbbell } else 226254885Sdumbbell lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; 227254885Sdumbbell } else { 228254885Sdumbbell if (ASIC_IS_R300(rdev)) 229254885Sdumbbell lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; 230254885Sdumbbell else 231254885Sdumbbell lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; 232254885Sdumbbell } 233254885Sdumbbell 234254885Sdumbbell WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); 235254885Sdumbbell WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); 236254885Sdumbbell WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl); 237254885Sdumbbell 238254885Sdumbbell if (rdev->family == CHIP_RV410) 239254885Sdumbbell WREG32(RADEON_CLOCK_CNTL_INDEX, 0); 240254885Sdumbbell 241254885Sdumbbell if (rdev->is_atom_bios) 242254885Sdumbbell radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 243254885Sdumbbell else 244254885Sdumbbell radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 245254885Sdumbbell} 246254885Sdumbbell 247254885Sdumbbellstatic bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, 248280183Sdumbbell const struct drm_display_mode *mode, 249254885Sdumbbell struct drm_display_mode *adjusted_mode) 250254885Sdumbbell{ 251254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 252254885Sdumbbell 253254885Sdumbbell /* set the active encoder to connector routing */ 254254885Sdumbbell radeon_encoder_set_active_device(encoder); 255254885Sdumbbell drm_mode_set_crtcinfo(adjusted_mode, 0); 256254885Sdumbbell 257254885Sdumbbell /* get the native mode for LVDS */ 258254885Sdumbbell if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) 259254885Sdumbbell radeon_panel_mode_fixup(encoder, adjusted_mode); 260254885Sdumbbell 261254885Sdumbbell return true; 262254885Sdumbbell} 263254885Sdumbbell 264254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { 265254885Sdumbbell .dpms = radeon_legacy_lvds_dpms, 266254885Sdumbbell .mode_fixup = radeon_legacy_mode_fixup, 267254885Sdumbbell .prepare = radeon_legacy_lvds_prepare, 268254885Sdumbbell .mode_set = radeon_legacy_lvds_mode_set, 269254885Sdumbbell .commit = radeon_legacy_lvds_commit, 270254885Sdumbbell .disable = radeon_legacy_encoder_disable, 271254885Sdumbbell}; 272254885Sdumbbell 273254885Sdumbbellu8 274254885Sdumbbellradeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder) 275254885Sdumbbell{ 276254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 277254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 278254885Sdumbbell u8 backlight_level; 279254885Sdumbbell 280254885Sdumbbell backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> 281254885Sdumbbell RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; 282254885Sdumbbell 283254885Sdumbbell return backlight_level; 284254885Sdumbbell} 285254885Sdumbbell 286254885Sdumbbellvoid 287254885Sdumbbellradeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level) 288254885Sdumbbell{ 289254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 290254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 291254885Sdumbbell int dpms_mode = DRM_MODE_DPMS_ON; 292254885Sdumbbell 293254885Sdumbbell if (radeon_encoder->enc_priv) { 294254885Sdumbbell if (rdev->is_atom_bios) { 295254885Sdumbbell struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; 296254885Sdumbbell if (lvds->backlight_level > 0) 297254885Sdumbbell dpms_mode = lvds->dpms_mode; 298254885Sdumbbell else 299254885Sdumbbell dpms_mode = DRM_MODE_DPMS_OFF; 300254885Sdumbbell lvds->backlight_level = level; 301254885Sdumbbell } else { 302254885Sdumbbell struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; 303254885Sdumbbell if (lvds->backlight_level > 0) 304254885Sdumbbell dpms_mode = lvds->dpms_mode; 305254885Sdumbbell else 306254885Sdumbbell dpms_mode = DRM_MODE_DPMS_OFF; 307254885Sdumbbell lvds->backlight_level = level; 308254885Sdumbbell } 309254885Sdumbbell } 310254885Sdumbbell 311254885Sdumbbell radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode); 312254885Sdumbbell} 313254885Sdumbbell 314254885Sdumbbell#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) 315254885Sdumbbell 316254885Sdumbbellstatic uint8_t radeon_legacy_lvds_level(struct backlight_device *bd) 317254885Sdumbbell{ 318254885Sdumbbell struct radeon_backlight_privdata *pdata = bl_get_data(bd); 319254885Sdumbbell uint8_t level; 320254885Sdumbbell 321254885Sdumbbell /* Convert brightness to hardware level */ 322254885Sdumbbell if (bd->props.brightness < 0) 323254885Sdumbbell level = 0; 324254885Sdumbbell else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) 325254885Sdumbbell level = RADEON_MAX_BL_LEVEL; 326254885Sdumbbell else 327254885Sdumbbell level = bd->props.brightness; 328254885Sdumbbell 329254885Sdumbbell if (pdata->negative) 330254885Sdumbbell level = RADEON_MAX_BL_LEVEL - level; 331254885Sdumbbell 332254885Sdumbbell return level; 333254885Sdumbbell} 334254885Sdumbbell 335254885Sdumbbellstatic int radeon_legacy_backlight_update_status(struct backlight_device *bd) 336254885Sdumbbell{ 337254885Sdumbbell struct radeon_backlight_privdata *pdata = bl_get_data(bd); 338254885Sdumbbell struct radeon_encoder *radeon_encoder = pdata->encoder; 339254885Sdumbbell 340254885Sdumbbell radeon_legacy_set_backlight_level(radeon_encoder, 341254885Sdumbbell radeon_legacy_lvds_level(bd)); 342254885Sdumbbell 343254885Sdumbbell return 0; 344254885Sdumbbell} 345254885Sdumbbell 346254885Sdumbbellstatic int radeon_legacy_backlight_get_brightness(struct backlight_device *bd) 347254885Sdumbbell{ 348254885Sdumbbell struct radeon_backlight_privdata *pdata = bl_get_data(bd); 349254885Sdumbbell struct radeon_encoder *radeon_encoder = pdata->encoder; 350254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 351254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 352254885Sdumbbell uint8_t backlight_level; 353254885Sdumbbell 354254885Sdumbbell backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> 355254885Sdumbbell RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; 356254885Sdumbbell 357254885Sdumbbell return pdata->negative ? RADEON_MAX_BL_LEVEL - backlight_level : backlight_level; 358254885Sdumbbell} 359254885Sdumbbell 360254885Sdumbbellstatic const struct backlight_ops radeon_backlight_ops = { 361254885Sdumbbell .get_brightness = radeon_legacy_backlight_get_brightness, 362254885Sdumbbell .update_status = radeon_legacy_backlight_update_status, 363254885Sdumbbell}; 364254885Sdumbbell 365254885Sdumbbellvoid radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, 366254885Sdumbbell struct drm_connector *drm_connector) 367254885Sdumbbell{ 368254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 369254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 370254885Sdumbbell struct backlight_device *bd; 371254885Sdumbbell struct backlight_properties props; 372254885Sdumbbell struct radeon_backlight_privdata *pdata; 373254885Sdumbbell uint8_t backlight_level; 374254885Sdumbbell char bl_name[16]; 375254885Sdumbbell 376254885Sdumbbell if (!radeon_encoder->enc_priv) 377254885Sdumbbell return; 378254885Sdumbbell 379254885Sdumbbell#ifdef CONFIG_PMAC_BACKLIGHT 380254885Sdumbbell if (!pmac_has_backlight_type("ati") && 381254885Sdumbbell !pmac_has_backlight_type("mnca")) 382254885Sdumbbell return; 383254885Sdumbbell#endif 384254885Sdumbbell 385254885Sdumbbell pdata = malloc(sizeof(struct radeon_backlight_privdata), 386280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT); 387254885Sdumbbell if (!pdata) { 388254885Sdumbbell DRM_ERROR("Memory allocation failed\n"); 389254885Sdumbbell goto error; 390254885Sdumbbell } 391254885Sdumbbell 392254885Sdumbbell memset(&props, 0, sizeof(props)); 393254885Sdumbbell props.max_brightness = RADEON_MAX_BL_LEVEL; 394254885Sdumbbell props.type = BACKLIGHT_RAW; 395254885Sdumbbell snprintf(bl_name, sizeof(bl_name), 396254885Sdumbbell "radeon_bl%d", dev->primary->index); 397254885Sdumbbell bd = backlight_device_register(bl_name, &drm_connector->kdev, 398254885Sdumbbell pdata, &radeon_backlight_ops, &props); 399254885Sdumbbell if (IS_ERR(bd)) { 400254885Sdumbbell DRM_ERROR("Backlight registration failed\n"); 401254885Sdumbbell goto error; 402254885Sdumbbell } 403254885Sdumbbell 404254885Sdumbbell pdata->encoder = radeon_encoder; 405254885Sdumbbell 406254885Sdumbbell backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >> 407254885Sdumbbell RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff; 408254885Sdumbbell 409254885Sdumbbell /* First, try to detect backlight level sense based on the assumption 410254885Sdumbbell * that firmware set it up at full brightness 411254885Sdumbbell */ 412254885Sdumbbell if (backlight_level == 0) 413254885Sdumbbell pdata->negative = true; 414254885Sdumbbell else if (backlight_level == 0xff) 415254885Sdumbbell pdata->negative = false; 416254885Sdumbbell else { 417254885Sdumbbell /* XXX hack... maybe some day we can figure out in what direction 418254885Sdumbbell * backlight should work on a given panel? 419254885Sdumbbell */ 420254885Sdumbbell pdata->negative = (rdev->family != CHIP_RV200 && 421254885Sdumbbell rdev->family != CHIP_RV250 && 422254885Sdumbbell rdev->family != CHIP_RV280 && 423254885Sdumbbell rdev->family != CHIP_RV350); 424254885Sdumbbell 425254885Sdumbbell#ifdef CONFIG_PMAC_BACKLIGHT 426254885Sdumbbell pdata->negative = (pdata->negative || 427254885Sdumbbell of_machine_is_compatible("PowerBook4,3") || 428254885Sdumbbell of_machine_is_compatible("PowerBook6,3") || 429254885Sdumbbell of_machine_is_compatible("PowerBook6,5")); 430254885Sdumbbell#endif 431254885Sdumbbell } 432254885Sdumbbell 433254885Sdumbbell if (rdev->is_atom_bios) { 434254885Sdumbbell struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; 435254885Sdumbbell lvds->bl_dev = bd; 436254885Sdumbbell } else { 437254885Sdumbbell struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; 438254885Sdumbbell lvds->bl_dev = bd; 439254885Sdumbbell } 440254885Sdumbbell 441254885Sdumbbell bd->props.brightness = radeon_legacy_backlight_get_brightness(bd); 442254885Sdumbbell bd->props.power = FB_BLANK_UNBLANK; 443254885Sdumbbell backlight_update_status(bd); 444254885Sdumbbell 445254885Sdumbbell DRM_INFO("radeon legacy LVDS backlight initialized\n"); 446254885Sdumbbell 447254885Sdumbbell return; 448254885Sdumbbell 449254885Sdumbbellerror: 450254885Sdumbbell free(pdata, DRM_MEM_DRIVER); 451254885Sdumbbell return; 452254885Sdumbbell} 453254885Sdumbbell 454254885Sdumbbellstatic void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder) 455254885Sdumbbell{ 456254885Sdumbbell struct drm_device *dev = radeon_encoder->base.dev; 457254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 458254885Sdumbbell struct backlight_device *bd = NULL; 459254885Sdumbbell 460254885Sdumbbell if (!radeon_encoder->enc_priv) 461254885Sdumbbell return; 462254885Sdumbbell 463254885Sdumbbell if (rdev->is_atom_bios) { 464254885Sdumbbell struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; 465254885Sdumbbell bd = lvds->bl_dev; 466254885Sdumbbell lvds->bl_dev = NULL; 467254885Sdumbbell } else { 468254885Sdumbbell struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; 469254885Sdumbbell bd = lvds->bl_dev; 470254885Sdumbbell lvds->bl_dev = NULL; 471254885Sdumbbell } 472254885Sdumbbell 473254885Sdumbbell if (bd) { 474254885Sdumbbell struct radeon_backlight_privdata *pdata; 475254885Sdumbbell 476254885Sdumbbell pdata = bl_get_data(bd); 477254885Sdumbbell backlight_device_unregister(bd); 478254885Sdumbbell free(pdata, DRM_MEM_DRIVER); 479254885Sdumbbell 480254885Sdumbbell DRM_INFO("radeon legacy LVDS backlight unloaded\n"); 481254885Sdumbbell } 482254885Sdumbbell} 483254885Sdumbbell 484254885Sdumbbell#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */ 485254885Sdumbbell 486254885Sdumbbellvoid radeon_legacy_backlight_init(struct radeon_encoder *encoder, 487254885Sdumbbell struct drm_connector *drm_connector) 488254885Sdumbbell{ 489254885Sdumbbell} 490254885Sdumbbell 491254885Sdumbbellstatic void radeon_legacy_backlight_exit(struct radeon_encoder *encoder) 492254885Sdumbbell{ 493254885Sdumbbell} 494254885Sdumbbell 495254885Sdumbbell#endif 496254885Sdumbbell 497254885Sdumbbell 498254885Sdumbbellstatic void radeon_lvds_enc_destroy(struct drm_encoder *encoder) 499254885Sdumbbell{ 500254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 501254885Sdumbbell 502254885Sdumbbell if (radeon_encoder->enc_priv) { 503254885Sdumbbell radeon_legacy_backlight_exit(radeon_encoder); 504254885Sdumbbell free(radeon_encoder->enc_priv, DRM_MEM_DRIVER); 505254885Sdumbbell } 506254885Sdumbbell drm_encoder_cleanup(encoder); 507254885Sdumbbell free(radeon_encoder, DRM_MEM_DRIVER); 508254885Sdumbbell} 509254885Sdumbbell 510254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { 511254885Sdumbbell .destroy = radeon_lvds_enc_destroy, 512254885Sdumbbell}; 513254885Sdumbbell 514254885Sdumbbellstatic void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode) 515254885Sdumbbell{ 516254885Sdumbbell struct drm_device *dev = encoder->dev; 517254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 518254885Sdumbbell uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 519254885Sdumbbell uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL); 520254885Sdumbbell uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); 521254885Sdumbbell 522254885Sdumbbell DRM_DEBUG_KMS("\n"); 523254885Sdumbbell 524254885Sdumbbell switch (mode) { 525254885Sdumbbell case DRM_MODE_DPMS_ON: 526254885Sdumbbell crtc_ext_cntl |= RADEON_CRTC_CRT_ON; 527254885Sdumbbell dac_cntl &= ~RADEON_DAC_PDWN; 528254885Sdumbbell dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | 529254885Sdumbbell RADEON_DAC_PDWN_G | 530254885Sdumbbell RADEON_DAC_PDWN_B); 531254885Sdumbbell break; 532254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 533254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 534254885Sdumbbell case DRM_MODE_DPMS_OFF: 535254885Sdumbbell crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; 536254885Sdumbbell dac_cntl |= RADEON_DAC_PDWN; 537254885Sdumbbell dac_macro_cntl |= (RADEON_DAC_PDWN_R | 538254885Sdumbbell RADEON_DAC_PDWN_G | 539254885Sdumbbell RADEON_DAC_PDWN_B); 540254885Sdumbbell break; 541254885Sdumbbell } 542254885Sdumbbell 543254885Sdumbbell /* handled in radeon_crtc_dpms() */ 544254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) 545254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 546254885Sdumbbell WREG32(RADEON_DAC_CNTL, dac_cntl); 547254885Sdumbbell WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); 548254885Sdumbbell 549254885Sdumbbell if (rdev->is_atom_bios) 550254885Sdumbbell radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 551254885Sdumbbell else 552254885Sdumbbell radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 553254885Sdumbbell 554254885Sdumbbell} 555254885Sdumbbell 556254885Sdumbbellstatic void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder) 557254885Sdumbbell{ 558254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 559254885Sdumbbell 560254885Sdumbbell if (rdev->is_atom_bios) 561254885Sdumbbell radeon_atom_output_lock(encoder, true); 562254885Sdumbbell else 563254885Sdumbbell radeon_combios_output_lock(encoder, true); 564254885Sdumbbell radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF); 565254885Sdumbbell} 566254885Sdumbbell 567254885Sdumbbellstatic void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) 568254885Sdumbbell{ 569254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 570254885Sdumbbell 571254885Sdumbbell radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON); 572254885Sdumbbell 573254885Sdumbbell if (rdev->is_atom_bios) 574254885Sdumbbell radeon_atom_output_lock(encoder, false); 575254885Sdumbbell else 576254885Sdumbbell radeon_combios_output_lock(encoder, false); 577254885Sdumbbell} 578254885Sdumbbell 579254885Sdumbbellstatic void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, 580254885Sdumbbell struct drm_display_mode *mode, 581254885Sdumbbell struct drm_display_mode *adjusted_mode) 582254885Sdumbbell{ 583254885Sdumbbell struct drm_device *dev = encoder->dev; 584254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 585254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 586254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 587254885Sdumbbell uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl; 588254885Sdumbbell 589254885Sdumbbell DRM_DEBUG_KMS("\n"); 590254885Sdumbbell 591254885Sdumbbell if (radeon_crtc->crtc_id == 0) { 592254885Sdumbbell if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { 593254885Sdumbbell disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & 594254885Sdumbbell ~(RADEON_DISP_DAC_SOURCE_MASK); 595254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 596254885Sdumbbell } else { 597254885Sdumbbell dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL); 598254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac2_cntl); 599254885Sdumbbell } 600254885Sdumbbell } else { 601254885Sdumbbell if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { 602254885Sdumbbell disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & 603254885Sdumbbell ~(RADEON_DISP_DAC_SOURCE_MASK); 604254885Sdumbbell disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; 605254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 606254885Sdumbbell } else { 607254885Sdumbbell dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL; 608254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac2_cntl); 609254885Sdumbbell } 610254885Sdumbbell } 611254885Sdumbbell 612254885Sdumbbell dac_cntl = (RADEON_DAC_MASK_ALL | 613254885Sdumbbell RADEON_DAC_VGA_ADR_EN | 614254885Sdumbbell /* TODO 6-bits */ 615254885Sdumbbell RADEON_DAC_8BIT_EN); 616254885Sdumbbell 617254885Sdumbbell WREG32_P(RADEON_DAC_CNTL, 618254885Sdumbbell dac_cntl, 619254885Sdumbbell RADEON_DAC_RANGE_CNTL | 620254885Sdumbbell RADEON_DAC_BLANKING); 621254885Sdumbbell 622254885Sdumbbell if (radeon_encoder->enc_priv) { 623254885Sdumbbell struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv; 624254885Sdumbbell dac_macro_cntl = p_dac->ps2_pdac_adj; 625254885Sdumbbell } else 626254885Sdumbbell dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); 627254885Sdumbbell dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B; 628254885Sdumbbell WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); 629254885Sdumbbell 630254885Sdumbbell if (rdev->is_atom_bios) 631254885Sdumbbell radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 632254885Sdumbbell else 633254885Sdumbbell radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 634254885Sdumbbell} 635254885Sdumbbell 636254885Sdumbbellstatic enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder, 637254885Sdumbbell struct drm_connector *connector) 638254885Sdumbbell{ 639254885Sdumbbell struct drm_device *dev = encoder->dev; 640254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 641254885Sdumbbell uint32_t vclk_ecp_cntl, crtc_ext_cntl; 642254885Sdumbbell uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; 643254885Sdumbbell enum drm_connector_status found = connector_status_disconnected; 644254885Sdumbbell bool color = true; 645254885Sdumbbell 646254885Sdumbbell /* just don't bother on RN50 those chip are often connected to remoting 647254885Sdumbbell * console hw and often we get failure to load detect those. So to make 648254885Sdumbbell * everyone happy report the encoder as always connected. 649254885Sdumbbell */ 650254885Sdumbbell if (ASIC_IS_RN50(rdev)) { 651254885Sdumbbell return connector_status_connected; 652254885Sdumbbell } 653254885Sdumbbell 654254885Sdumbbell /* save the regs we need */ 655254885Sdumbbell vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); 656254885Sdumbbell crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 657254885Sdumbbell dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); 658254885Sdumbbell dac_cntl = RREG32(RADEON_DAC_CNTL); 659254885Sdumbbell dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); 660254885Sdumbbell 661254885Sdumbbell tmp = vclk_ecp_cntl & 662254885Sdumbbell ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); 663254885Sdumbbell WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); 664254885Sdumbbell 665254885Sdumbbell tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; 666254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, tmp); 667254885Sdumbbell 668254885Sdumbbell tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | 669254885Sdumbbell RADEON_DAC_FORCE_DATA_EN; 670254885Sdumbbell 671254885Sdumbbell if (color) 672254885Sdumbbell tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; 673254885Sdumbbell else 674254885Sdumbbell tmp |= RADEON_DAC_FORCE_DATA_SEL_G; 675254885Sdumbbell 676254885Sdumbbell if (ASIC_IS_R300(rdev)) 677254885Sdumbbell tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); 678254885Sdumbbell else if (ASIC_IS_RV100(rdev)) 679254885Sdumbbell tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT); 680254885Sdumbbell else 681254885Sdumbbell tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); 682254885Sdumbbell 683254885Sdumbbell WREG32(RADEON_DAC_EXT_CNTL, tmp); 684254885Sdumbbell 685254885Sdumbbell tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); 686254885Sdumbbell tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; 687254885Sdumbbell WREG32(RADEON_DAC_CNTL, tmp); 688254885Sdumbbell 689254885Sdumbbell tmp = dac_macro_cntl; 690254885Sdumbbell tmp &= ~(RADEON_DAC_PDWN_R | 691254885Sdumbbell RADEON_DAC_PDWN_G | 692254885Sdumbbell RADEON_DAC_PDWN_B); 693254885Sdumbbell 694254885Sdumbbell WREG32(RADEON_DAC_MACRO_CNTL, tmp); 695254885Sdumbbell 696280183Sdumbbell mdelay(2); 697254885Sdumbbell 698254885Sdumbbell if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) 699254885Sdumbbell found = connector_status_connected; 700254885Sdumbbell 701254885Sdumbbell /* restore the regs we used */ 702254885Sdumbbell WREG32(RADEON_DAC_CNTL, dac_cntl); 703254885Sdumbbell WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); 704254885Sdumbbell WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); 705254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 706254885Sdumbbell WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); 707254885Sdumbbell 708254885Sdumbbell return found; 709254885Sdumbbell} 710254885Sdumbbell 711254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { 712254885Sdumbbell .dpms = radeon_legacy_primary_dac_dpms, 713254885Sdumbbell .mode_fixup = radeon_legacy_mode_fixup, 714254885Sdumbbell .prepare = radeon_legacy_primary_dac_prepare, 715254885Sdumbbell .mode_set = radeon_legacy_primary_dac_mode_set, 716254885Sdumbbell .commit = radeon_legacy_primary_dac_commit, 717254885Sdumbbell .detect = radeon_legacy_primary_dac_detect, 718254885Sdumbbell .disable = radeon_legacy_encoder_disable, 719254885Sdumbbell}; 720254885Sdumbbell 721254885Sdumbbell 722254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = { 723254885Sdumbbell .destroy = radeon_enc_destroy, 724254885Sdumbbell}; 725254885Sdumbbell 726254885Sdumbbellstatic void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) 727254885Sdumbbell{ 728254885Sdumbbell struct drm_device *dev = encoder->dev; 729254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 730254885Sdumbbell uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL); 731254885Sdumbbell DRM_DEBUG_KMS("\n"); 732254885Sdumbbell 733254885Sdumbbell switch (mode) { 734254885Sdumbbell case DRM_MODE_DPMS_ON: 735254885Sdumbbell fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); 736254885Sdumbbell break; 737254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 738254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 739254885Sdumbbell case DRM_MODE_DPMS_OFF: 740254885Sdumbbell fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); 741254885Sdumbbell break; 742254885Sdumbbell } 743254885Sdumbbell 744254885Sdumbbell WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl); 745254885Sdumbbell 746254885Sdumbbell if (rdev->is_atom_bios) 747254885Sdumbbell radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 748254885Sdumbbell else 749254885Sdumbbell radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 750254885Sdumbbell 751254885Sdumbbell} 752254885Sdumbbell 753254885Sdumbbellstatic void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder) 754254885Sdumbbell{ 755254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 756254885Sdumbbell 757254885Sdumbbell if (rdev->is_atom_bios) 758254885Sdumbbell radeon_atom_output_lock(encoder, true); 759254885Sdumbbell else 760254885Sdumbbell radeon_combios_output_lock(encoder, true); 761254885Sdumbbell radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF); 762254885Sdumbbell} 763254885Sdumbbell 764254885Sdumbbellstatic void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) 765254885Sdumbbell{ 766254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 767254885Sdumbbell 768254885Sdumbbell radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON); 769254885Sdumbbell 770254885Sdumbbell if (rdev->is_atom_bios) 771254885Sdumbbell radeon_atom_output_lock(encoder, true); 772254885Sdumbbell else 773254885Sdumbbell radeon_combios_output_lock(encoder, true); 774254885Sdumbbell} 775254885Sdumbbell 776254885Sdumbbellstatic void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, 777254885Sdumbbell struct drm_display_mode *mode, 778254885Sdumbbell struct drm_display_mode *adjusted_mode) 779254885Sdumbbell{ 780254885Sdumbbell struct drm_device *dev = encoder->dev; 781254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 782254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 783254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 784254885Sdumbbell uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl; 785254885Sdumbbell int i; 786254885Sdumbbell 787254885Sdumbbell DRM_DEBUG_KMS("\n"); 788254885Sdumbbell 789254885Sdumbbell tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); 790254885Sdumbbell tmp &= 0xfffff; 791254885Sdumbbell if (rdev->family == CHIP_RV280) { 792254885Sdumbbell /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ 793254885Sdumbbell tmp ^= (1 << 22); 794254885Sdumbbell tmds_pll_cntl ^= (1 << 22); 795254885Sdumbbell } 796254885Sdumbbell 797254885Sdumbbell if (radeon_encoder->enc_priv) { 798254885Sdumbbell struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv; 799254885Sdumbbell 800254885Sdumbbell for (i = 0; i < 4; i++) { 801254885Sdumbbell if (tmds->tmds_pll[i].freq == 0) 802254885Sdumbbell break; 803254885Sdumbbell if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) { 804254885Sdumbbell tmp = tmds->tmds_pll[i].value ; 805254885Sdumbbell break; 806254885Sdumbbell } 807254885Sdumbbell } 808254885Sdumbbell } 809254885Sdumbbell 810254885Sdumbbell if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) { 811254885Sdumbbell if (tmp & 0xfff00000) 812254885Sdumbbell tmds_pll_cntl = tmp; 813254885Sdumbbell else { 814254885Sdumbbell tmds_pll_cntl &= 0xfff00000; 815254885Sdumbbell tmds_pll_cntl |= tmp; 816254885Sdumbbell } 817254885Sdumbbell } else 818254885Sdumbbell tmds_pll_cntl = tmp; 819254885Sdumbbell 820254885Sdumbbell tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) & 821254885Sdumbbell ~(RADEON_TMDS_TRANSMITTER_PLLRST); 822254885Sdumbbell 823254885Sdumbbell if (rdev->family == CHIP_R200 || 824254885Sdumbbell rdev->family == CHIP_R100 || 825254885Sdumbbell ASIC_IS_R300(rdev)) 826254885Sdumbbell tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); 827254885Sdumbbell else /* RV chips got this bit reversed */ 828254885Sdumbbell tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN; 829254885Sdumbbell 830254885Sdumbbell fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) | 831254885Sdumbbell (RADEON_FP_CRTC_DONT_SHADOW_VPAR | 832254885Sdumbbell RADEON_FP_CRTC_DONT_SHADOW_HEND)); 833254885Sdumbbell 834254885Sdumbbell fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); 835254885Sdumbbell 836254885Sdumbbell fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN | 837254885Sdumbbell RADEON_FP_DFP_SYNC_SEL | 838254885Sdumbbell RADEON_FP_CRT_SYNC_SEL | 839254885Sdumbbell RADEON_FP_CRTC_LOCK_8DOT | 840254885Sdumbbell RADEON_FP_USE_SHADOW_EN | 841254885Sdumbbell RADEON_FP_CRTC_USE_SHADOW_VEND | 842254885Sdumbbell RADEON_FP_CRT_SYNC_ALT); 843254885Sdumbbell 844254885Sdumbbell if (1) /* FIXME rgbBits == 8 */ 845254885Sdumbbell fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ 846254885Sdumbbell else 847254885Sdumbbell fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ 848254885Sdumbbell 849254885Sdumbbell if (radeon_crtc->crtc_id == 0) { 850254885Sdumbbell if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { 851254885Sdumbbell fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; 852254885Sdumbbell if (radeon_encoder->rmx_type != RMX_OFF) 853254885Sdumbbell fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; 854254885Sdumbbell else 855254885Sdumbbell fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; 856254885Sdumbbell } else 857254885Sdumbbell fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2; 858254885Sdumbbell } else { 859254885Sdumbbell if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { 860254885Sdumbbell fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; 861254885Sdumbbell fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; 862254885Sdumbbell } else 863254885Sdumbbell fp_gen_cntl |= RADEON_FP_SEL_CRTC2; 864254885Sdumbbell } 865254885Sdumbbell 866254885Sdumbbell WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl); 867254885Sdumbbell WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl); 868254885Sdumbbell WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl); 869254885Sdumbbell 870254885Sdumbbell if (rdev->is_atom_bios) 871254885Sdumbbell radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 872254885Sdumbbell else 873254885Sdumbbell radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 874254885Sdumbbell} 875254885Sdumbbell 876254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = { 877254885Sdumbbell .dpms = radeon_legacy_tmds_int_dpms, 878254885Sdumbbell .mode_fixup = radeon_legacy_mode_fixup, 879254885Sdumbbell .prepare = radeon_legacy_tmds_int_prepare, 880254885Sdumbbell .mode_set = radeon_legacy_tmds_int_mode_set, 881254885Sdumbbell .commit = radeon_legacy_tmds_int_commit, 882254885Sdumbbell .disable = radeon_legacy_encoder_disable, 883254885Sdumbbell}; 884254885Sdumbbell 885254885Sdumbbell 886254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = { 887254885Sdumbbell .destroy = radeon_enc_destroy, 888254885Sdumbbell}; 889254885Sdumbbell 890254885Sdumbbellstatic void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode) 891254885Sdumbbell{ 892254885Sdumbbell struct drm_device *dev = encoder->dev; 893254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 894254885Sdumbbell uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 895254885Sdumbbell DRM_DEBUG_KMS("\n"); 896254885Sdumbbell 897254885Sdumbbell switch (mode) { 898254885Sdumbbell case DRM_MODE_DPMS_ON: 899254885Sdumbbell fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; 900254885Sdumbbell fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); 901254885Sdumbbell break; 902254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 903254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 904254885Sdumbbell case DRM_MODE_DPMS_OFF: 905254885Sdumbbell fp2_gen_cntl |= RADEON_FP2_BLANK_EN; 906254885Sdumbbell fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); 907254885Sdumbbell break; 908254885Sdumbbell } 909254885Sdumbbell 910254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 911254885Sdumbbell 912254885Sdumbbell if (rdev->is_atom_bios) 913254885Sdumbbell radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 914254885Sdumbbell else 915254885Sdumbbell radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 916254885Sdumbbell 917254885Sdumbbell} 918254885Sdumbbell 919254885Sdumbbellstatic void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder) 920254885Sdumbbell{ 921254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 922254885Sdumbbell 923254885Sdumbbell if (rdev->is_atom_bios) 924254885Sdumbbell radeon_atom_output_lock(encoder, true); 925254885Sdumbbell else 926254885Sdumbbell radeon_combios_output_lock(encoder, true); 927254885Sdumbbell radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF); 928254885Sdumbbell} 929254885Sdumbbell 930254885Sdumbbellstatic void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder) 931254885Sdumbbell{ 932254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 933254885Sdumbbell radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON); 934254885Sdumbbell 935254885Sdumbbell if (rdev->is_atom_bios) 936254885Sdumbbell radeon_atom_output_lock(encoder, false); 937254885Sdumbbell else 938254885Sdumbbell radeon_combios_output_lock(encoder, false); 939254885Sdumbbell} 940254885Sdumbbell 941254885Sdumbbellstatic void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, 942254885Sdumbbell struct drm_display_mode *mode, 943254885Sdumbbell struct drm_display_mode *adjusted_mode) 944254885Sdumbbell{ 945254885Sdumbbell struct drm_device *dev = encoder->dev; 946254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 947254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 948254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 949254885Sdumbbell uint32_t fp2_gen_cntl; 950254885Sdumbbell 951254885Sdumbbell DRM_DEBUG_KMS("\n"); 952254885Sdumbbell 953254885Sdumbbell if (rdev->is_atom_bios) { 954254885Sdumbbell radeon_encoder->pixel_clock = adjusted_mode->clock; 955254885Sdumbbell atombios_dvo_setup(encoder, ATOM_ENABLE); 956254885Sdumbbell fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 957254885Sdumbbell } else { 958254885Sdumbbell fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 959254885Sdumbbell 960254885Sdumbbell if (1) /* FIXME rgbBits == 8 */ 961254885Sdumbbell fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ 962254885Sdumbbell else 963254885Sdumbbell fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ 964254885Sdumbbell 965254885Sdumbbell fp2_gen_cntl &= ~(RADEON_FP2_ON | 966254885Sdumbbell RADEON_FP2_DVO_EN | 967254885Sdumbbell RADEON_FP2_DVO_RATE_SEL_SDR); 968254885Sdumbbell 969254885Sdumbbell /* XXX: these are oem specific */ 970254885Sdumbbell if (ASIC_IS_R300(rdev)) { 971254885Sdumbbell if ((dev->pci_device == 0x4850) && 972254885Sdumbbell (dev->pci_subvendor == 0x1028) && 973254885Sdumbbell (dev->pci_subdevice == 0x2001)) /* Dell Inspiron 8600 */ 974254885Sdumbbell fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE; 975254885Sdumbbell else 976254885Sdumbbell fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE; 977254885Sdumbbell 978254885Sdumbbell /*if (mode->clock > 165000) 979254885Sdumbbell fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/ 980254885Sdumbbell } 981254885Sdumbbell if (!radeon_combios_external_tmds_setup(encoder)) 982254885Sdumbbell radeon_external_tmds_setup(encoder); 983254885Sdumbbell } 984254885Sdumbbell 985254885Sdumbbell if (radeon_crtc->crtc_id == 0) { 986254885Sdumbbell if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { 987254885Sdumbbell fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; 988254885Sdumbbell if (radeon_encoder->rmx_type != RMX_OFF) 989254885Sdumbbell fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; 990254885Sdumbbell else 991254885Sdumbbell fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; 992254885Sdumbbell } else 993254885Sdumbbell fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; 994254885Sdumbbell } else { 995254885Sdumbbell if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { 996254885Sdumbbell fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; 997254885Sdumbbell fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; 998254885Sdumbbell } else 999254885Sdumbbell fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; 1000254885Sdumbbell } 1001254885Sdumbbell 1002254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 1003254885Sdumbbell 1004254885Sdumbbell if (rdev->is_atom_bios) 1005254885Sdumbbell radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1006254885Sdumbbell else 1007254885Sdumbbell radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1008254885Sdumbbell} 1009254885Sdumbbell 1010254885Sdumbbellstatic void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) 1011254885Sdumbbell{ 1012254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1013254885Sdumbbell /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ 1014254885Sdumbbell free(radeon_encoder->enc_priv, DRM_MEM_DRIVER); 1015254885Sdumbbell drm_encoder_cleanup(encoder); 1016254885Sdumbbell free(radeon_encoder, DRM_MEM_DRIVER); 1017254885Sdumbbell} 1018254885Sdumbbell 1019254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = { 1020254885Sdumbbell .dpms = radeon_legacy_tmds_ext_dpms, 1021254885Sdumbbell .mode_fixup = radeon_legacy_mode_fixup, 1022254885Sdumbbell .prepare = radeon_legacy_tmds_ext_prepare, 1023254885Sdumbbell .mode_set = radeon_legacy_tmds_ext_mode_set, 1024254885Sdumbbell .commit = radeon_legacy_tmds_ext_commit, 1025254885Sdumbbell .disable = radeon_legacy_encoder_disable, 1026254885Sdumbbell}; 1027254885Sdumbbell 1028254885Sdumbbell 1029254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = { 1030254885Sdumbbell .destroy = radeon_ext_tmds_enc_destroy, 1031254885Sdumbbell}; 1032254885Sdumbbell 1033254885Sdumbbellstatic void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) 1034254885Sdumbbell{ 1035254885Sdumbbell struct drm_device *dev = encoder->dev; 1036254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1037254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1038254885Sdumbbell uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0; 1039254885Sdumbbell uint32_t tv_master_cntl = 0; 1040254885Sdumbbell bool is_tv; 1041254885Sdumbbell DRM_DEBUG_KMS("\n"); 1042254885Sdumbbell 1043254885Sdumbbell is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false; 1044254885Sdumbbell 1045254885Sdumbbell if (rdev->family == CHIP_R200) 1046254885Sdumbbell fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 1047254885Sdumbbell else { 1048254885Sdumbbell if (is_tv) 1049254885Sdumbbell tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); 1050254885Sdumbbell else 1051254885Sdumbbell crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1052254885Sdumbbell tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); 1053254885Sdumbbell } 1054254885Sdumbbell 1055254885Sdumbbell switch (mode) { 1056254885Sdumbbell case DRM_MODE_DPMS_ON: 1057254885Sdumbbell if (rdev->family == CHIP_R200) { 1058254885Sdumbbell fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); 1059254885Sdumbbell } else { 1060254885Sdumbbell if (is_tv) 1061254885Sdumbbell tv_master_cntl |= RADEON_TV_ON; 1062254885Sdumbbell else 1063254885Sdumbbell crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; 1064254885Sdumbbell 1065254885Sdumbbell if (rdev->family == CHIP_R420 || 1066254885Sdumbbell rdev->family == CHIP_R423 || 1067254885Sdumbbell rdev->family == CHIP_RV410) 1068254885Sdumbbell tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | 1069254885Sdumbbell R420_TV_DAC_GDACPD | 1070254885Sdumbbell R420_TV_DAC_BDACPD | 1071254885Sdumbbell RADEON_TV_DAC_BGSLEEP); 1072254885Sdumbbell else 1073254885Sdumbbell tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | 1074254885Sdumbbell RADEON_TV_DAC_GDACPD | 1075254885Sdumbbell RADEON_TV_DAC_BDACPD | 1076254885Sdumbbell RADEON_TV_DAC_BGSLEEP); 1077254885Sdumbbell } 1078254885Sdumbbell break; 1079254885Sdumbbell case DRM_MODE_DPMS_STANDBY: 1080254885Sdumbbell case DRM_MODE_DPMS_SUSPEND: 1081254885Sdumbbell case DRM_MODE_DPMS_OFF: 1082254885Sdumbbell if (rdev->family == CHIP_R200) 1083254885Sdumbbell fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); 1084254885Sdumbbell else { 1085254885Sdumbbell if (is_tv) 1086254885Sdumbbell tv_master_cntl &= ~RADEON_TV_ON; 1087254885Sdumbbell else 1088254885Sdumbbell crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; 1089254885Sdumbbell 1090254885Sdumbbell if (rdev->family == CHIP_R420 || 1091254885Sdumbbell rdev->family == CHIP_R423 || 1092254885Sdumbbell rdev->family == CHIP_RV410) 1093254885Sdumbbell tv_dac_cntl |= (R420_TV_DAC_RDACPD | 1094254885Sdumbbell R420_TV_DAC_GDACPD | 1095254885Sdumbbell R420_TV_DAC_BDACPD | 1096254885Sdumbbell RADEON_TV_DAC_BGSLEEP); 1097254885Sdumbbell else 1098254885Sdumbbell tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | 1099254885Sdumbbell RADEON_TV_DAC_GDACPD | 1100254885Sdumbbell RADEON_TV_DAC_BDACPD | 1101254885Sdumbbell RADEON_TV_DAC_BGSLEEP); 1102254885Sdumbbell } 1103254885Sdumbbell break; 1104254885Sdumbbell } 1105254885Sdumbbell 1106254885Sdumbbell if (rdev->family == CHIP_R200) { 1107254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 1108254885Sdumbbell } else { 1109254885Sdumbbell if (is_tv) 1110254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); 1111254885Sdumbbell /* handled in radeon_crtc_dpms() */ 1112254885Sdumbbell else if (!(rdev->flags & RADEON_SINGLE_CRTC)) 1113254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 1114254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 1115254885Sdumbbell } 1116254885Sdumbbell 1117254885Sdumbbell if (rdev->is_atom_bios) 1118254885Sdumbbell radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1119254885Sdumbbell else 1120254885Sdumbbell radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 1121254885Sdumbbell 1122254885Sdumbbell} 1123254885Sdumbbell 1124254885Sdumbbellstatic void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder) 1125254885Sdumbbell{ 1126254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 1127254885Sdumbbell 1128254885Sdumbbell if (rdev->is_atom_bios) 1129254885Sdumbbell radeon_atom_output_lock(encoder, true); 1130254885Sdumbbell else 1131254885Sdumbbell radeon_combios_output_lock(encoder, true); 1132254885Sdumbbell radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF); 1133254885Sdumbbell} 1134254885Sdumbbell 1135254885Sdumbbellstatic void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder) 1136254885Sdumbbell{ 1137254885Sdumbbell struct radeon_device *rdev = encoder->dev->dev_private; 1138254885Sdumbbell 1139254885Sdumbbell radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON); 1140254885Sdumbbell 1141254885Sdumbbell if (rdev->is_atom_bios) 1142254885Sdumbbell radeon_atom_output_lock(encoder, true); 1143254885Sdumbbell else 1144254885Sdumbbell radeon_combios_output_lock(encoder, true); 1145254885Sdumbbell} 1146254885Sdumbbell 1147254885Sdumbbellstatic void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, 1148254885Sdumbbell struct drm_display_mode *mode, 1149254885Sdumbbell struct drm_display_mode *adjusted_mode) 1150254885Sdumbbell{ 1151254885Sdumbbell struct drm_device *dev = encoder->dev; 1152254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1153254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 1154254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1155254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 1156254885Sdumbbell uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; 1157254885Sdumbbell uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0; 1158254885Sdumbbell bool is_tv = false; 1159254885Sdumbbell 1160254885Sdumbbell DRM_DEBUG_KMS("\n"); 1161254885Sdumbbell 1162254885Sdumbbell is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false; 1163254885Sdumbbell 1164254885Sdumbbell if (rdev->family != CHIP_R200) { 1165254885Sdumbbell tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); 1166254885Sdumbbell if (rdev->family == CHIP_R420 || 1167254885Sdumbbell rdev->family == CHIP_R423 || 1168254885Sdumbbell rdev->family == CHIP_RV410) { 1169254885Sdumbbell tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | 1170254885Sdumbbell RADEON_TV_DAC_BGADJ_MASK | 1171254885Sdumbbell R420_TV_DAC_DACADJ_MASK | 1172254885Sdumbbell R420_TV_DAC_RDACPD | 1173254885Sdumbbell R420_TV_DAC_GDACPD | 1174254885Sdumbbell R420_TV_DAC_BDACPD | 1175254885Sdumbbell R420_TV_DAC_TVENABLE); 1176254885Sdumbbell } else { 1177254885Sdumbbell tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | 1178254885Sdumbbell RADEON_TV_DAC_BGADJ_MASK | 1179254885Sdumbbell RADEON_TV_DAC_DACADJ_MASK | 1180254885Sdumbbell RADEON_TV_DAC_RDACPD | 1181254885Sdumbbell RADEON_TV_DAC_GDACPD | 1182254885Sdumbbell RADEON_TV_DAC_BDACPD); 1183254885Sdumbbell } 1184254885Sdumbbell 1185254885Sdumbbell tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD; 1186254885Sdumbbell 1187254885Sdumbbell if (is_tv) { 1188254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 1189254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J || 1190254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_M || 1191254885Sdumbbell tv_dac->tv_std == TV_STD_PAL_60) 1192254885Sdumbbell tv_dac_cntl |= tv_dac->ntsc_tvdac_adj; 1193254885Sdumbbell else 1194254885Sdumbbell tv_dac_cntl |= tv_dac->pal_tvdac_adj; 1195254885Sdumbbell 1196254885Sdumbbell if (tv_dac->tv_std == TV_STD_NTSC || 1197254885Sdumbbell tv_dac->tv_std == TV_STD_NTSC_J) 1198254885Sdumbbell tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; 1199254885Sdumbbell else 1200254885Sdumbbell tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; 1201254885Sdumbbell } else 1202254885Sdumbbell tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 | 1203254885Sdumbbell tv_dac->ps2_tvdac_adj); 1204254885Sdumbbell 1205254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 1206254885Sdumbbell } 1207254885Sdumbbell 1208254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1209254885Sdumbbell gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1; 1210254885Sdumbbell disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); 1211254885Sdumbbell } else if (rdev->family != CHIP_R200) 1212254885Sdumbbell disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); 1213254885Sdumbbell else if (rdev->family == CHIP_R200) 1214254885Sdumbbell fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 1215254885Sdumbbell 1216254885Sdumbbell if (rdev->family >= CHIP_R200) 1217254885Sdumbbell disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); 1218254885Sdumbbell 1219254885Sdumbbell if (is_tv) { 1220254885Sdumbbell uint32_t dac_cntl; 1221254885Sdumbbell 1222254885Sdumbbell dac_cntl = RREG32(RADEON_DAC_CNTL); 1223254885Sdumbbell dac_cntl &= ~RADEON_DAC_TVO_EN; 1224254885Sdumbbell WREG32(RADEON_DAC_CNTL, dac_cntl); 1225254885Sdumbbell 1226254885Sdumbbell if (ASIC_IS_R300(rdev)) 1227254885Sdumbbell gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1; 1228254885Sdumbbell 1229254885Sdumbbell dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL; 1230254885Sdumbbell if (radeon_crtc->crtc_id == 0) { 1231254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1232254885Sdumbbell disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; 1233254885Sdumbbell disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC | 1234254885Sdumbbell RADEON_DISP_TV_SOURCE_CRTC); 1235254885Sdumbbell } 1236254885Sdumbbell if (rdev->family >= CHIP_R200) { 1237254885Sdumbbell disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2; 1238254885Sdumbbell } else { 1239254885Sdumbbell disp_hw_debug |= RADEON_CRT2_DISP1_SEL; 1240254885Sdumbbell } 1241254885Sdumbbell } else { 1242254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1243254885Sdumbbell disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; 1244254885Sdumbbell disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC; 1245254885Sdumbbell } 1246254885Sdumbbell if (rdev->family >= CHIP_R200) { 1247254885Sdumbbell disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2; 1248254885Sdumbbell } else { 1249254885Sdumbbell disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; 1250254885Sdumbbell } 1251254885Sdumbbell } 1252254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac2_cntl); 1253254885Sdumbbell } else { 1254254885Sdumbbell 1255254885Sdumbbell dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL; 1256254885Sdumbbell 1257254885Sdumbbell if (radeon_crtc->crtc_id == 0) { 1258254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1259254885Sdumbbell disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; 1260254885Sdumbbell disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; 1261254885Sdumbbell } else if (rdev->family == CHIP_R200) { 1262254885Sdumbbell fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | 1263254885Sdumbbell RADEON_FP2_DVO_RATE_SEL_SDR); 1264254885Sdumbbell } else 1265254885Sdumbbell disp_hw_debug |= RADEON_CRT2_DISP1_SEL; 1266254885Sdumbbell } else { 1267254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1268254885Sdumbbell disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; 1269254885Sdumbbell disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; 1270254885Sdumbbell } else if (rdev->family == CHIP_R200) { 1271254885Sdumbbell fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | 1272254885Sdumbbell RADEON_FP2_DVO_RATE_SEL_SDR); 1273254885Sdumbbell fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; 1274254885Sdumbbell } else 1275254885Sdumbbell disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; 1276254885Sdumbbell } 1277254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac2_cntl); 1278254885Sdumbbell } 1279254885Sdumbbell 1280254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1281254885Sdumbbell WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); 1282254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 1283254885Sdumbbell } else if (rdev->family != CHIP_R200) 1284254885Sdumbbell WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); 1285254885Sdumbbell else if (rdev->family == CHIP_R200) 1286254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 1287254885Sdumbbell 1288254885Sdumbbell if (rdev->family >= CHIP_R200) 1289254885Sdumbbell WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl); 1290254885Sdumbbell 1291254885Sdumbbell if (is_tv) 1292254885Sdumbbell radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode); 1293254885Sdumbbell 1294254885Sdumbbell if (rdev->is_atom_bios) 1295254885Sdumbbell radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1296254885Sdumbbell else 1297254885Sdumbbell radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); 1298254885Sdumbbell 1299254885Sdumbbell} 1300254885Sdumbbell 1301254885Sdumbbellstatic bool r300_legacy_tv_detect(struct drm_encoder *encoder, 1302254885Sdumbbell struct drm_connector *connector) 1303254885Sdumbbell{ 1304254885Sdumbbell struct drm_device *dev = encoder->dev; 1305254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1306254885Sdumbbell uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; 1307254885Sdumbbell uint32_t disp_output_cntl, gpiopad_a, tmp; 1308254885Sdumbbell bool found = false; 1309254885Sdumbbell 1310254885Sdumbbell /* save regs needed */ 1311254885Sdumbbell gpiopad_a = RREG32(RADEON_GPIOPAD_A); 1312254885Sdumbbell dac_cntl2 = RREG32(RADEON_DAC_CNTL2); 1313254885Sdumbbell crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1314254885Sdumbbell dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); 1315254885Sdumbbell tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); 1316254885Sdumbbell disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); 1317254885Sdumbbell 1318254885Sdumbbell WREG32_P(RADEON_GPIOPAD_A, 0, ~1); 1319254885Sdumbbell 1320254885Sdumbbell WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL); 1321254885Sdumbbell 1322254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, 1323254885Sdumbbell RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT); 1324254885Sdumbbell 1325254885Sdumbbell tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; 1326254885Sdumbbell tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; 1327254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); 1328254885Sdumbbell 1329254885Sdumbbell WREG32(RADEON_DAC_EXT_CNTL, 1330254885Sdumbbell RADEON_DAC2_FORCE_BLANK_OFF_EN | 1331254885Sdumbbell RADEON_DAC2_FORCE_DATA_EN | 1332254885Sdumbbell RADEON_DAC_FORCE_DATA_SEL_RGB | 1333254885Sdumbbell (0xec << RADEON_DAC_FORCE_DATA_SHIFT)); 1334254885Sdumbbell 1335254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, 1336254885Sdumbbell RADEON_TV_DAC_STD_NTSC | 1337254885Sdumbbell (8 << RADEON_TV_DAC_BGADJ_SHIFT) | 1338254885Sdumbbell (6 << RADEON_TV_DAC_DACADJ_SHIFT)); 1339254885Sdumbbell 1340254885Sdumbbell RREG32(RADEON_TV_DAC_CNTL); 1341280183Sdumbbell mdelay(4); 1342254885Sdumbbell 1343254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, 1344254885Sdumbbell RADEON_TV_DAC_NBLANK | 1345254885Sdumbbell RADEON_TV_DAC_NHOLD | 1346254885Sdumbbell RADEON_TV_MONITOR_DETECT_EN | 1347254885Sdumbbell RADEON_TV_DAC_STD_NTSC | 1348254885Sdumbbell (8 << RADEON_TV_DAC_BGADJ_SHIFT) | 1349254885Sdumbbell (6 << RADEON_TV_DAC_DACADJ_SHIFT)); 1350254885Sdumbbell 1351254885Sdumbbell RREG32(RADEON_TV_DAC_CNTL); 1352280183Sdumbbell mdelay(6); 1353254885Sdumbbell 1354254885Sdumbbell tmp = RREG32(RADEON_TV_DAC_CNTL); 1355254885Sdumbbell if ((tmp & RADEON_TV_DAC_GDACDET) != 0) { 1356254885Sdumbbell found = true; 1357254885Sdumbbell DRM_DEBUG_KMS("S-video TV connection detected\n"); 1358254885Sdumbbell } else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) { 1359254885Sdumbbell found = true; 1360254885Sdumbbell DRM_DEBUG_KMS("Composite TV connection detected\n"); 1361254885Sdumbbell } 1362254885Sdumbbell 1363254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 1364254885Sdumbbell WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); 1365254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 1366254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 1367254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac_cntl2); 1368254885Sdumbbell WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); 1369254885Sdumbbell return found; 1370254885Sdumbbell} 1371254885Sdumbbell 1372254885Sdumbbellstatic bool radeon_legacy_tv_detect(struct drm_encoder *encoder, 1373254885Sdumbbell struct drm_connector *connector) 1374254885Sdumbbell{ 1375254885Sdumbbell struct drm_device *dev = encoder->dev; 1376254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1377254885Sdumbbell uint32_t tv_dac_cntl, dac_cntl2; 1378254885Sdumbbell uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp; 1379254885Sdumbbell bool found = false; 1380254885Sdumbbell 1381254885Sdumbbell if (ASIC_IS_R300(rdev)) 1382254885Sdumbbell return r300_legacy_tv_detect(encoder, connector); 1383254885Sdumbbell 1384254885Sdumbbell dac_cntl2 = RREG32(RADEON_DAC_CNTL2); 1385254885Sdumbbell tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); 1386254885Sdumbbell tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); 1387254885Sdumbbell config_cntl = RREG32(RADEON_CONFIG_CNTL); 1388254885Sdumbbell tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL); 1389254885Sdumbbell 1390254885Sdumbbell tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; 1391254885Sdumbbell WREG32(RADEON_DAC_CNTL2, tmp); 1392254885Sdumbbell 1393254885Sdumbbell tmp = tv_master_cntl | RADEON_TV_ON; 1394254885Sdumbbell tmp &= ~(RADEON_TV_ASYNC_RST | 1395254885Sdumbbell RADEON_RESTART_PHASE_FIX | 1396254885Sdumbbell RADEON_CRT_FIFO_CE_EN | 1397254885Sdumbbell RADEON_TV_FIFO_CE_EN | 1398254885Sdumbbell RADEON_RE_SYNC_NOW_SEL_MASK); 1399254885Sdumbbell tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; 1400254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, tmp); 1401254885Sdumbbell 1402254885Sdumbbell tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | 1403254885Sdumbbell RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | 1404254885Sdumbbell (8 << RADEON_TV_DAC_BGADJ_SHIFT); 1405254885Sdumbbell 1406254885Sdumbbell if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) 1407254885Sdumbbell tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); 1408254885Sdumbbell else 1409254885Sdumbbell tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); 1410254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tmp); 1411254885Sdumbbell 1412254885Sdumbbell tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | 1413254885Sdumbbell RADEON_RED_MX_FORCE_DAC_DATA | 1414254885Sdumbbell RADEON_GRN_MX_FORCE_DAC_DATA | 1415254885Sdumbbell RADEON_BLU_MX_FORCE_DAC_DATA | 1416254885Sdumbbell (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); 1417254885Sdumbbell WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); 1418254885Sdumbbell 1419280183Sdumbbell mdelay(3); 1420254885Sdumbbell tmp = RREG32(RADEON_TV_DAC_CNTL); 1421254885Sdumbbell if (tmp & RADEON_TV_DAC_GDACDET) { 1422254885Sdumbbell found = true; 1423254885Sdumbbell DRM_DEBUG_KMS("S-video TV connection detected\n"); 1424254885Sdumbbell } else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) { 1425254885Sdumbbell found = true; 1426254885Sdumbbell DRM_DEBUG_KMS("Composite TV connection detected\n"); 1427254885Sdumbbell } 1428254885Sdumbbell 1429254885Sdumbbell WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); 1430254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 1431254885Sdumbbell WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); 1432254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac_cntl2); 1433254885Sdumbbell return found; 1434254885Sdumbbell} 1435254885Sdumbbell 1436254885Sdumbbellstatic bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, 1437254885Sdumbbell struct drm_connector *connector) 1438254885Sdumbbell{ 1439254885Sdumbbell struct drm_device *dev = encoder->dev; 1440254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1441254885Sdumbbell uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; 1442254885Sdumbbell uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; 1443254885Sdumbbell uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; 1444254885Sdumbbell uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; 1445254885Sdumbbell uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; 1446254885Sdumbbell bool found = false; 1447254885Sdumbbell int i; 1448254885Sdumbbell 1449254885Sdumbbell /* save the regs we need */ 1450254885Sdumbbell gpio_monid = RREG32(RADEON_GPIO_MONID); 1451254885Sdumbbell fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); 1452254885Sdumbbell disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); 1453254885Sdumbbell crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1454254885Sdumbbell disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); 1455254885Sdumbbell disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); 1456254885Sdumbbell disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); 1457254885Sdumbbell disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); 1458254885Sdumbbell disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); 1459254885Sdumbbell disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); 1460254885Sdumbbell crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); 1461254885Sdumbbell crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); 1462254885Sdumbbell crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); 1463254885Sdumbbell crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); 1464254885Sdumbbell 1465254885Sdumbbell tmp = RREG32(RADEON_GPIO_MONID); 1466254885Sdumbbell tmp &= ~RADEON_GPIO_A_0; 1467254885Sdumbbell WREG32(RADEON_GPIO_MONID, tmp); 1468254885Sdumbbell 1469254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | 1470254885Sdumbbell RADEON_FP2_PANEL_FORMAT | 1471254885Sdumbbell R200_FP2_SOURCE_SEL_TRANS_UNIT | 1472254885Sdumbbell RADEON_FP2_DVO_EN | 1473254885Sdumbbell R200_FP2_DVO_RATE_SEL_SDR)); 1474254885Sdumbbell 1475254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | 1476254885Sdumbbell RADEON_DISP_TRANS_MATRIX_GRAPHICS)); 1477254885Sdumbbell 1478254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | 1479254885Sdumbbell RADEON_CRTC2_DISP_REQ_EN_B)); 1480254885Sdumbbell 1481254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); 1482254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); 1483254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); 1484254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); 1485254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); 1486254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); 1487254885Sdumbbell 1488254885Sdumbbell WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); 1489254885Sdumbbell WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); 1490254885Sdumbbell WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); 1491254885Sdumbbell WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); 1492254885Sdumbbell 1493254885Sdumbbell for (i = 0; i < 200; i++) { 1494254885Sdumbbell tmp = RREG32(RADEON_GPIO_MONID); 1495254885Sdumbbell if (tmp & RADEON_GPIO_Y_0) 1496254885Sdumbbell found = true; 1497254885Sdumbbell 1498254885Sdumbbell if (found) 1499254885Sdumbbell break; 1500254885Sdumbbell 1501254885Sdumbbell if (!drm_can_sleep()) 1502280183Sdumbbell mdelay(1); 1503254885Sdumbbell else 1504254885Sdumbbell DRM_MSLEEP(1); 1505254885Sdumbbell } 1506254885Sdumbbell 1507254885Sdumbbell /* restore the regs we used */ 1508254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); 1509254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); 1510254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); 1511254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); 1512254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); 1513254885Sdumbbell WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); 1514254885Sdumbbell WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); 1515254885Sdumbbell WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); 1516254885Sdumbbell WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); 1517254885Sdumbbell WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); 1518254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 1519254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 1520254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 1521254885Sdumbbell WREG32(RADEON_GPIO_MONID, gpio_monid); 1522254885Sdumbbell 1523254885Sdumbbell return found; 1524254885Sdumbbell} 1525254885Sdumbbell 1526254885Sdumbbellstatic enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, 1527254885Sdumbbell struct drm_connector *connector) 1528254885Sdumbbell{ 1529254885Sdumbbell struct drm_device *dev = encoder->dev; 1530254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1531254885Sdumbbell uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; 1532254885Sdumbbell uint32_t gpiopad_a = 0, pixclks_cntl, tmp; 1533254885Sdumbbell uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0; 1534254885Sdumbbell enum drm_connector_status found = connector_status_disconnected; 1535254885Sdumbbell struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1536254885Sdumbbell struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 1537254885Sdumbbell bool color = true; 1538254885Sdumbbell struct drm_crtc *crtc; 1539254885Sdumbbell 1540254885Sdumbbell /* find out if crtc2 is in use or if this encoder is using it */ 1541254885Sdumbbell list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1542254885Sdumbbell struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 1543254885Sdumbbell if ((radeon_crtc->crtc_id == 1) && crtc->enabled) { 1544254885Sdumbbell if (encoder->crtc != crtc) { 1545254885Sdumbbell return connector_status_disconnected; 1546254885Sdumbbell } 1547254885Sdumbbell } 1548254885Sdumbbell } 1549254885Sdumbbell 1550254885Sdumbbell if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO || 1551254885Sdumbbell connector->connector_type == DRM_MODE_CONNECTOR_Composite || 1552254885Sdumbbell connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) { 1553254885Sdumbbell bool tv_detect; 1554254885Sdumbbell 1555254885Sdumbbell if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT)) 1556254885Sdumbbell return connector_status_disconnected; 1557254885Sdumbbell 1558254885Sdumbbell tv_detect = radeon_legacy_tv_detect(encoder, connector); 1559254885Sdumbbell if (tv_detect && tv_dac) 1560254885Sdumbbell found = connector_status_connected; 1561254885Sdumbbell return found; 1562254885Sdumbbell } 1563254885Sdumbbell 1564254885Sdumbbell /* don't probe if the encoder is being used for something else not CRT related */ 1565254885Sdumbbell if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) { 1566254885Sdumbbell DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device); 1567254885Sdumbbell return connector_status_disconnected; 1568254885Sdumbbell } 1569254885Sdumbbell 1570254885Sdumbbell /* R200 uses an external DAC for secondary DAC */ 1571254885Sdumbbell if (rdev->family == CHIP_R200) { 1572254885Sdumbbell if (radeon_legacy_ext_dac_detect(encoder, connector)) 1573254885Sdumbbell found = connector_status_connected; 1574254885Sdumbbell return found; 1575254885Sdumbbell } 1576254885Sdumbbell 1577254885Sdumbbell /* save the regs we need */ 1578254885Sdumbbell pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); 1579254885Sdumbbell 1580254885Sdumbbell if (rdev->flags & RADEON_SINGLE_CRTC) { 1581254885Sdumbbell crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 1582254885Sdumbbell } else { 1583254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1584254885Sdumbbell gpiopad_a = RREG32(RADEON_GPIOPAD_A); 1585254885Sdumbbell disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); 1586254885Sdumbbell } else { 1587254885Sdumbbell disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); 1588254885Sdumbbell } 1589254885Sdumbbell crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1590254885Sdumbbell } 1591254885Sdumbbell tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); 1592254885Sdumbbell dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); 1593254885Sdumbbell dac_cntl2 = RREG32(RADEON_DAC_CNTL2); 1594254885Sdumbbell 1595254885Sdumbbell tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb 1596254885Sdumbbell | RADEON_PIX2CLK_DAC_ALWAYS_ONb); 1597254885Sdumbbell WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); 1598254885Sdumbbell 1599254885Sdumbbell if (rdev->flags & RADEON_SINGLE_CRTC) { 1600254885Sdumbbell tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; 1601254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, tmp); 1602254885Sdumbbell } else { 1603254885Sdumbbell tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; 1604254885Sdumbbell tmp |= RADEON_CRTC2_CRT2_ON | 1605254885Sdumbbell (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); 1606254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, tmp); 1607254885Sdumbbell 1608254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1609254885Sdumbbell WREG32_P(RADEON_GPIOPAD_A, 1, ~1); 1610254885Sdumbbell tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; 1611254885Sdumbbell tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; 1612254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); 1613254885Sdumbbell } else { 1614254885Sdumbbell tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; 1615254885Sdumbbell WREG32(RADEON_DISP_HW_DEBUG, tmp); 1616254885Sdumbbell } 1617254885Sdumbbell } 1618254885Sdumbbell 1619254885Sdumbbell tmp = RADEON_TV_DAC_NBLANK | 1620254885Sdumbbell RADEON_TV_DAC_NHOLD | 1621254885Sdumbbell RADEON_TV_MONITOR_DETECT_EN | 1622254885Sdumbbell RADEON_TV_DAC_STD_PS2; 1623254885Sdumbbell 1624254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tmp); 1625254885Sdumbbell 1626254885Sdumbbell tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | 1627254885Sdumbbell RADEON_DAC2_FORCE_DATA_EN; 1628254885Sdumbbell 1629254885Sdumbbell if (color) 1630254885Sdumbbell tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; 1631254885Sdumbbell else 1632254885Sdumbbell tmp |= RADEON_DAC_FORCE_DATA_SEL_G; 1633254885Sdumbbell 1634254885Sdumbbell if (ASIC_IS_R300(rdev)) 1635254885Sdumbbell tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); 1636254885Sdumbbell else 1637254885Sdumbbell tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); 1638254885Sdumbbell 1639254885Sdumbbell WREG32(RADEON_DAC_EXT_CNTL, tmp); 1640254885Sdumbbell 1641254885Sdumbbell tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; 1642254885Sdumbbell WREG32(RADEON_DAC_CNTL2, tmp); 1643254885Sdumbbell 1644280183Sdumbbell mdelay(10); 1645254885Sdumbbell 1646254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1647254885Sdumbbell if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) 1648254885Sdumbbell found = connector_status_connected; 1649254885Sdumbbell } else { 1650254885Sdumbbell if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) 1651254885Sdumbbell found = connector_status_connected; 1652254885Sdumbbell } 1653254885Sdumbbell 1654254885Sdumbbell /* restore regs we used */ 1655254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac_cntl2); 1656254885Sdumbbell WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); 1657254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 1658254885Sdumbbell 1659254885Sdumbbell if (rdev->flags & RADEON_SINGLE_CRTC) { 1660254885Sdumbbell WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 1661254885Sdumbbell } else { 1662254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 1663254885Sdumbbell if (ASIC_IS_R300(rdev)) { 1664254885Sdumbbell WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); 1665254885Sdumbbell WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); 1666254885Sdumbbell } else { 1667254885Sdumbbell WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); 1668254885Sdumbbell } 1669254885Sdumbbell } 1670254885Sdumbbell 1671254885Sdumbbell WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); 1672254885Sdumbbell 1673254885Sdumbbell return found; 1674254885Sdumbbell 1675254885Sdumbbell} 1676254885Sdumbbell 1677254885Sdumbbellstatic const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = { 1678254885Sdumbbell .dpms = radeon_legacy_tv_dac_dpms, 1679254885Sdumbbell .mode_fixup = radeon_legacy_mode_fixup, 1680254885Sdumbbell .prepare = radeon_legacy_tv_dac_prepare, 1681254885Sdumbbell .mode_set = radeon_legacy_tv_dac_mode_set, 1682254885Sdumbbell .commit = radeon_legacy_tv_dac_commit, 1683254885Sdumbbell .detect = radeon_legacy_tv_dac_detect, 1684254885Sdumbbell .disable = radeon_legacy_encoder_disable, 1685254885Sdumbbell}; 1686254885Sdumbbell 1687254885Sdumbbell 1688254885Sdumbbellstatic const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = { 1689254885Sdumbbell .destroy = radeon_enc_destroy, 1690254885Sdumbbell}; 1691254885Sdumbbell 1692254885Sdumbbell 1693254885Sdumbbellstatic struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder) 1694254885Sdumbbell{ 1695254885Sdumbbell struct drm_device *dev = encoder->base.dev; 1696254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1697254885Sdumbbell struct radeon_encoder_int_tmds *tmds = NULL; 1698254885Sdumbbell bool ret; 1699254885Sdumbbell 1700254885Sdumbbell tmds = malloc(sizeof(struct radeon_encoder_int_tmds), 1701280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 1702254885Sdumbbell 1703254885Sdumbbell if (!tmds) 1704254885Sdumbbell return NULL; 1705254885Sdumbbell 1706254885Sdumbbell if (rdev->is_atom_bios) 1707254885Sdumbbell ret = radeon_atombios_get_tmds_info(encoder, tmds); 1708254885Sdumbbell else 1709254885Sdumbbell ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds); 1710254885Sdumbbell 1711254885Sdumbbell if (ret == false) 1712254885Sdumbbell radeon_legacy_get_tmds_info_from_table(encoder, tmds); 1713254885Sdumbbell 1714254885Sdumbbell return tmds; 1715254885Sdumbbell} 1716254885Sdumbbell 1717254885Sdumbbellstatic struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder) 1718254885Sdumbbell{ 1719254885Sdumbbell struct drm_device *dev = encoder->base.dev; 1720254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1721254885Sdumbbell struct radeon_encoder_ext_tmds *tmds = NULL; 1722254885Sdumbbell bool ret; 1723254885Sdumbbell 1724254885Sdumbbell if (rdev->is_atom_bios) 1725254885Sdumbbell return NULL; 1726254885Sdumbbell 1727254885Sdumbbell tmds = malloc(sizeof(struct radeon_encoder_ext_tmds), 1728280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 1729254885Sdumbbell 1730254885Sdumbbell if (!tmds) 1731254885Sdumbbell return NULL; 1732254885Sdumbbell 1733254885Sdumbbell ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds); 1734254885Sdumbbell 1735254885Sdumbbell if (ret == false) 1736254885Sdumbbell radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds); 1737254885Sdumbbell 1738254885Sdumbbell return tmds; 1739254885Sdumbbell} 1740254885Sdumbbell 1741254885Sdumbbellvoid 1742254885Sdumbbellradeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device) 1743254885Sdumbbell{ 1744254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1745254885Sdumbbell struct drm_encoder *encoder; 1746254885Sdumbbell struct radeon_encoder *radeon_encoder; 1747254885Sdumbbell 1748254885Sdumbbell /* see if we already added it */ 1749254885Sdumbbell list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 1750254885Sdumbbell radeon_encoder = to_radeon_encoder(encoder); 1751254885Sdumbbell if (radeon_encoder->encoder_enum == encoder_enum) { 1752254885Sdumbbell radeon_encoder->devices |= supported_device; 1753254885Sdumbbell return; 1754254885Sdumbbell } 1755254885Sdumbbell 1756254885Sdumbbell } 1757254885Sdumbbell 1758254885Sdumbbell /* add a new one */ 1759254885Sdumbbell radeon_encoder = malloc(sizeof(struct radeon_encoder), 1760280183Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 1761254885Sdumbbell if (!radeon_encoder) 1762254885Sdumbbell return; 1763254885Sdumbbell 1764254885Sdumbbell encoder = &radeon_encoder->base; 1765254885Sdumbbell if (rdev->flags & RADEON_SINGLE_CRTC) 1766254885Sdumbbell encoder->possible_crtcs = 0x1; 1767254885Sdumbbell else 1768254885Sdumbbell encoder->possible_crtcs = 0x3; 1769254885Sdumbbell 1770254885Sdumbbell radeon_encoder->enc_priv = NULL; 1771254885Sdumbbell 1772254885Sdumbbell radeon_encoder->encoder_enum = encoder_enum; 1773254885Sdumbbell radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1774254885Sdumbbell radeon_encoder->devices = supported_device; 1775254885Sdumbbell radeon_encoder->rmx_type = RMX_OFF; 1776254885Sdumbbell 1777254885Sdumbbell switch (radeon_encoder->encoder_id) { 1778254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1779254885Sdumbbell encoder->possible_crtcs = 0x1; 1780254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS); 1781254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); 1782254885Sdumbbell if (rdev->is_atom_bios) 1783254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); 1784254885Sdumbbell else 1785254885Sdumbbell radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder); 1786254885Sdumbbell radeon_encoder->rmx_type = RMX_FULL; 1787254885Sdumbbell break; 1788254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1789254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS); 1790254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); 1791254885Sdumbbell radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder); 1792254885Sdumbbell break; 1793254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1794254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC); 1795254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs); 1796254885Sdumbbell if (rdev->is_atom_bios) 1797254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder); 1798254885Sdumbbell else 1799254885Sdumbbell radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder); 1800254885Sdumbbell break; 1801254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1802254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC); 1803254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); 1804254885Sdumbbell if (rdev->is_atom_bios) 1805254885Sdumbbell radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder); 1806254885Sdumbbell else 1807254885Sdumbbell radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder); 1808254885Sdumbbell break; 1809254885Sdumbbell case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1810254885Sdumbbell drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS); 1811254885Sdumbbell drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs); 1812254885Sdumbbell if (!rdev->is_atom_bios) 1813254885Sdumbbell radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder); 1814254885Sdumbbell break; 1815254885Sdumbbell } 1816254885Sdumbbell} 1817