]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drm/radeon/kms: Add support for interrupts on r6xx/r7xx chips (v3)
[~andy/linux] / drivers / gpu / drm / radeon / radeon_legacy_encoders.c
index b1547f700d739eeb9787b2e55a09b826e6af3d57..df00515e81fa20870d73e9d797b5b19e681758b5 100644 (file)
@@ -107,8 +107,6 @@ static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
        else
                radeon_combios_output_lock(encoder, true);
        radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-       radeon_encoder_set_active_device(encoder);
 }
 
 static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
@@ -138,7 +136,14 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
        lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
 
        lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
-       if ((!rdev->is_atom_bios)) {
+       if (rdev->is_atom_bios) {
+               /* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
+                * need to call that on resume to set up the reg properly.
+                */
+               radeon_encoder->pixel_clock = adjusted_mode->clock;
+               atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
+               lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+       } else {
                struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
                if (lvds) {
                        DRM_DEBUG("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
@@ -149,8 +154,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
                                             (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
                } else
                        lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-       } else
-               lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+       }
        lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
        lvds_gen_cntl &= ~(RADEON_LVDS_ON |
                           RADEON_LVDS_BLON |
@@ -186,23 +190,32 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
                radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 }
 
-static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
-                                         struct drm_display_mode *mode,
-                                         struct drm_display_mode *adjusted_mode)
+static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
+                                    struct drm_display_mode *mode,
+                                    struct drm_display_mode *adjusted_mode)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
+       /* set the active encoder to connector routing */
+       radeon_encoder_set_active_device(encoder);
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-       if (radeon_encoder->rmx_type != RMX_OFF)
-               radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
+       /* get the native mode for LVDS */
+       if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
+               struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+               int mode_id = adjusted_mode->base.id;
+               *adjusted_mode = *native_mode;
+               adjusted_mode->hdisplay = mode->hdisplay;
+               adjusted_mode->vdisplay = mode->vdisplay;
+               adjusted_mode->base.id = mode_id;
+       }
 
        return true;
 }
 
 static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
        .dpms = radeon_legacy_lvds_dpms,
-       .mode_fixup = radeon_legacy_lvds_mode_fixup,
+       .mode_fixup = radeon_legacy_mode_fixup,
        .prepare = radeon_legacy_lvds_prepare,
        .mode_set = radeon_legacy_lvds_mode_set,
        .commit = radeon_legacy_lvds_commit,
@@ -214,16 +227,6 @@ static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
        .destroy = radeon_enc_destroy,
 };
 
-static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder,
-                                                struct drm_display_mode *mode,
-                                                struct drm_display_mode *adjusted_mode)
-{
-
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-       return true;
-}
-
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -272,7 +275,6 @@ static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
        else
                radeon_combios_output_lock(encoder, true);
        radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
-       radeon_encoder_set_active_device(encoder);
 }
 
 static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
@@ -410,7 +412,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
 
 static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
        .dpms = radeon_legacy_primary_dac_dpms,
-       .mode_fixup = radeon_legacy_primary_dac_mode_fixup,
+       .mode_fixup = radeon_legacy_mode_fixup,
        .prepare = radeon_legacy_primary_dac_prepare,
        .mode_set = radeon_legacy_primary_dac_mode_set,
        .commit = radeon_legacy_primary_dac_commit,
@@ -423,16 +425,6 @@ static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
        .destroy = radeon_enc_destroy,
 };
 
-static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder,
-                                             struct drm_display_mode *mode,
-                                             struct drm_display_mode *adjusted_mode)
-{
-
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-       return true;
-}
-
 static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -468,7 +460,6 @@ static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
        else
                radeon_combios_output_lock(encoder, true);
        radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
-       radeon_encoder_set_active_device(encoder);
 }
 
 static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
@@ -543,6 +534,14 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
 
     fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
 
+    fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
+                    RADEON_FP_DFP_SYNC_SEL |
+                    RADEON_FP_CRT_SYNC_SEL |
+                    RADEON_FP_CRTC_LOCK_8DOT |
+                    RADEON_FP_USE_SHADOW_EN |
+                    RADEON_FP_CRTC_USE_SHADOW_VEND |
+                    RADEON_FP_CRT_SYNC_ALT);
+
     if (1) /*  FIXME rgbBits == 8 */
            fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
     else
@@ -556,7 +555,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
                    else
                            fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
            } else
-                   fp_gen_cntl |= RADEON_FP_SEL_CRTC1;
+                   fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
     } else {
            if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
                    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
@@ -577,7 +576,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
 
 static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
        .dpms = radeon_legacy_tmds_int_dpms,
-       .mode_fixup = radeon_legacy_tmds_int_mode_fixup,
+       .mode_fixup = radeon_legacy_mode_fixup,
        .prepare = radeon_legacy_tmds_int_prepare,
        .mode_set = radeon_legacy_tmds_int_mode_set,
        .commit = radeon_legacy_tmds_int_commit,
@@ -589,16 +588,6 @@ static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
        .destroy = radeon_enc_destroy,
 };
 
-static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder,
-                                             struct drm_display_mode *mode,
-                                             struct drm_display_mode *adjusted_mode)
-{
-
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-       return true;
-}
-
 static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -636,7 +625,6 @@ static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
        else
                radeon_combios_output_lock(encoder, true);
        radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
-       radeon_encoder_set_active_device(encoder);
 }
 
 static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
@@ -690,6 +678,8 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
                        /*if (mode->clock > 165000)
                          fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
                }
+               if (!radeon_combios_external_tmds_setup(encoder))
+                       radeon_external_tmds_setup(encoder);
        }
 
        if (radeon_crtc->crtc_id == 0) {
@@ -717,9 +707,22 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
                radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 }
 
+static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
+{
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
+       if (tmds) {
+               if (tmds->i2c_bus)
+                       radeon_i2c_destroy(tmds->i2c_bus);
+       }
+       kfree(radeon_encoder->enc_priv);
+       drm_encoder_cleanup(encoder);
+       kfree(radeon_encoder);
+}
+
 static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
        .dpms = radeon_legacy_tmds_ext_dpms,
-       .mode_fixup = radeon_legacy_tmds_ext_mode_fixup,
+       .mode_fixup = radeon_legacy_mode_fixup,
        .prepare = radeon_legacy_tmds_ext_prepare,
        .mode_set = radeon_legacy_tmds_ext_mode_set,
        .commit = radeon_legacy_tmds_ext_commit,
@@ -728,19 +731,9 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs
 
 
 static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
-       .destroy = radeon_enc_destroy,
+       .destroy = radeon_ext_tmds_enc_destroy,
 };
 
-static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder,
-                                           struct drm_display_mode *mode,
-                                           struct drm_display_mode *adjusted_mode)
-{
-
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-       return true;
-}
-
 static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -839,7 +832,6 @@ static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
        else
                radeon_combios_output_lock(encoder, true);
        radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
-       radeon_encoder_set_active_device(encoder);
 }
 
 static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
@@ -881,7 +873,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
                                        R420_TV_DAC_DACADJ_MASK |
                                        R420_TV_DAC_RDACPD |
                                        R420_TV_DAC_GDACPD |
-                                       R420_TV_DAC_GDACPD |
+                                       R420_TV_DAC_BDACPD |
                                        R420_TV_DAC_TVENABLE);
                } else {
                        tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
@@ -889,7 +881,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
                                        RADEON_TV_DAC_DACADJ_MASK |
                                        RADEON_TV_DAC_RDACPD |
                                        RADEON_TV_DAC_GDACPD |
-                                       RADEON_TV_DAC_GDACPD);
+                                       RADEON_TV_DAC_BDACPD);
                }
 
                /*  FIXME TV */
@@ -1258,7 +1250,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
 
 static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
        .dpms = radeon_legacy_tv_dac_dpms,
-       .mode_fixup = radeon_legacy_tv_dac_mode_fixup,
+       .mode_fixup = radeon_legacy_mode_fixup,
        .prepare = radeon_legacy_tv_dac_prepare,
        .mode_set = radeon_legacy_tv_dac_mode_set,
        .commit = radeon_legacy_tv_dac_commit,
@@ -1295,6 +1287,29 @@ static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon
        return tmds;
 }
 
+static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
+{
+       struct drm_device *dev = encoder->base.dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder_ext_tmds *tmds = NULL;
+       bool ret;
+
+       if (rdev->is_atom_bios)
+               return NULL;
+
+       tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL);
+
+       if (!tmds)
+               return NULL;
+
+       ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
+
+       if (ret == false)
+               radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
+
+       return tmds;
+}
+
 void
 radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
 {
@@ -1318,8 +1333,10 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
                return;
 
        encoder = &radeon_encoder->base;
-       encoder->possible_crtcs = 0x3;
-       encoder->possible_clones = 0;
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               encoder->possible_crtcs = 0x1;
+       else
+               encoder->possible_crtcs = 0x3;
 
        radeon_encoder->enc_priv = NULL;
 
@@ -1363,7 +1380,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
                drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
                drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
                if (!rdev->is_atom_bios)
-                       radeon_combios_get_ext_tmds_info(radeon_encoder);
+                       radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
                break;
        }
 }