drm: move radeon_fixed.h to shared drm_fixed.h header
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / radeon_legacy_crtc.c
index 5794364..7701d42 100644 (file)
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/radeon_drm.h>
-#include "radeon_fixed.h"
+#include <drm/drm_fixed.h>
 #include "radeon.h"
 #include "atom.h"
 
+static void radeon_overscan_setup(struct drm_crtc *crtc,
+                                 struct drm_display_mode *mode)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+       WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0);
+       WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0);
+       WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0);
+}
+
 static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
-                                      struct drm_display_mode *mode,
-                                      struct drm_display_mode *adjusted_mode)
+                                      struct drm_display_mode *mode)
 {
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
@@ -292,8 +303,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        uint32_t mask;
 
        if (radeon_crtc->crtc_id)
-               mask = (RADEON_CRTC2_EN |
-                       RADEON_CRTC2_DISP_DIS |
+               mask = (RADEON_CRTC2_DISP_DIS |
                        RADEON_CRTC2_VSYNC_DIS |
                        RADEON_CRTC2_HSYNC_DIS |
                        RADEON_CRTC2_DISP_REQ_EN_B);
@@ -305,7 +315,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                if (radeon_crtc->crtc_id)
-                       WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask);
+                       WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask));
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
                                                                         RADEON_CRTC_DISP_REQ_EN_B));
@@ -313,83 +323,25 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                }
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
+               radeon_crtc->enabled = true;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
                if (radeon_crtc->crtc_id)
-                       WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
+                       WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask));
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
                                                                                    RADEON_CRTC_DISP_REQ_EN_B));
                        WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
                }
+               radeon_crtc->enabled = false;
                break;
        }
-}
-
-/* properly set crtc bpp when using atombios */
-void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-       int format;
-       uint32_t crtc_gen_cntl;
-       uint32_t disp_merge_cntl;
-       uint32_t crtc_pitch;
-
-       switch (crtc->fb->bits_per_pixel) {
-       case 8:
-               format = 2;
-               break;
-       case 15:      /*  555 */
-               format = 3;
-               break;
-       case 16:      /*  565 */
-               format = 4;
-               break;
-       case 24:      /*  RGB */
-               format = 5;
-               break;
-       case 32:      /* xRGB */
-               format = 6;
-               break;
-       default:
-               return;
-       }
-
-       crtc_pitch  = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) +
-                       ((crtc->fb->bits_per_pixel * 8) - 1)) /
-                      (crtc->fb->bits_per_pixel * 8));
-       crtc_pitch |= crtc_pitch << 16;
-
-       WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
 
-       switch (radeon_crtc->crtc_id) {
-       case 0:
-               disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
-               disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-               WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
-
-               crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
-               crtc_gen_cntl |= (format << 8);
-               crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
-               WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
-               break;
-       case 1:
-               disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
-               disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
-               WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
-
-               crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
-               crtc_gen_cntl |= (format << 8);
-               WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl);
-               WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
-               WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
-               break;
-       }
+       /* adjust pm to dpms change */
+       radeon_pm_compute_clocks(rdev);
 }
 
 int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
@@ -400,12 +352,14 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_framebuffer *radeon_fb;
        struct drm_gem_object *obj;
+       struct radeon_bo *rbo;
        uint64_t base;
        uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
        uint32_t crtc_pitch, pitch_pixels;
        uint32_t tiling_flags;
        int format;
        uint32_t gen_cntl_reg, gen_cntl_val;
+       int r;
 
        DRM_DEBUG("\n");
        /* no fb bound */
@@ -436,13 +390,25 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                return false;
        }
 
+       /* Pin framebuffer & get tilling informations */
        obj = radeon_fb->obj;
-       if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
+       rbo = obj->driver_private;
+       r = radeon_bo_reserve(rbo, false);
+       if (unlikely(r != 0))
+               return r;
+       r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base);
+       if (unlikely(r != 0)) {
+               radeon_bo_unreserve(rbo);
                return -EINVAL;
        }
+       radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
+       radeon_bo_unreserve(rbo);
+       if (tiling_flags & RADEON_TILING_MICRO)
+               DRM_ERROR("trying to scanout microtiled buffer\n");
+
        /* if scanout was in GTT this really wouldn't work */
        /* crtc offset is from display base addr not FB location */
-       radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
+       radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start;
 
        base -= radeon_crtc->legacy_display_base_addr;
 
@@ -454,10 +420,6 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                       (crtc->fb->bits_per_pixel * 8));
        crtc_pitch |= crtc_pitch << 16;
 
-       radeon_object_get_tiling_flags(obj->driver_private,
-                                      &tiling_flags, NULL);
-       if (tiling_flags & RADEON_TILING_MICRO)
-               DRM_ERROR("trying to scanout microtiled buffer\n");
 
        if (tiling_flags & RADEON_TILING_MACRO) {
                if (ASIC_IS_R300(rdev))
@@ -535,7 +497,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 
        if (old_fb && old_fb != crtc->fb) {
                radeon_fb = to_radeon_framebuffer(old_fb);
-               radeon_gem_object_unpin(radeon_fb->obj);
+               rbo = radeon_fb->obj->driver_private;
+               r = radeon_bo_reserve(rbo, false);
+               if (unlikely(r != 0))
+                       return r;
+               radeon_bo_unpin(rbo);
+               radeon_bo_unreserve(rbo);
        }
 
        /* Bytes per pixel may have changed */
@@ -620,39 +587,12 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                                   ? RADEON_CRTC_V_SYNC_POL
                                   : 0));
 
-       /* TODO -> Dell Server */
-       if (0) {
-               uint32_t disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
-               uint32_t tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
-               uint32_t dac2_cntl = RREG32(RADEON_DAC_CNTL2);
-               uint32_t crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
-
-               dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
-               dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
-
-               /* For CRT on DAC2, don't turn it on if BIOS didn't
-                  enable it, even it's detected.
-               */
-               disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
-               tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
-               tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
-
-               WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-               WREG32(RADEON_DAC_CNTL2, dac2_cntl);
-               WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
-       }
-
        if (radeon_crtc->crtc_id) {
                uint32_t crtc2_gen_cntl;
                uint32_t disp2_merge_cntl;
 
-               /* check to see if TV DAC is enabled for another crtc and keep it enabled */
-               if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON)
-                       crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
-               else
-                       crtc2_gen_cntl = 0;
-
+               /* if TV DAC is enabled for another crtc and keep it enabled */
+               crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080;
                crtc2_gen_cntl |= ((format << 8)
                                   | RADEON_CRTC2_VSYNC_DIS
                                   | RADEON_CRTC2_HSYNC_DIS
@@ -668,6 +608,10 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                                      ? RADEON_CRTC2_INTERLACE_EN
                                      : 0));
 
+               /* rs4xx chips seem to like to have the crtc enabled when the timing is set */
+               if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
+                       crtc2_gen_cntl |= RADEON_CRTC2_EN;
+
                disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
                disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
 
@@ -681,7 +625,8 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                uint32_t crtc_ext_cntl;
                uint32_t disp_merge_cntl;
 
-               crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
+               crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000;
+               crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN
                                 | (format << 8)
                                 | RADEON_CRTC_DISP_REQ_EN_B
                                 | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -694,6 +639,10 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
                                    ? RADEON_CRTC_INTERLACE_EN
                                    : 0));
 
+               /* rs4xx chips seem to like to have the crtc enabled when the timing is set */
+               if ((rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480))
+                       crtc_gen_cntl |= RADEON_CRTC_EN;
+
                crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
                crtc_ext_cntl |= (RADEON_XCRT_CNT_EN |
                                  RADEON_CRTC_VSYNC_DIS |
@@ -733,7 +682,6 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        uint32_t post_divider = 0;
        uint32_t freq = 0;
        uint8_t pll_gain;
-       int pll_flags = RADEON_PLL_LEGACY;
        bool use_bios_divs = false;
        /* PLL registers */
        uint32_t pll_ref_div = 0;
@@ -767,10 +715,16 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        else
                pll = &rdev->clock.p1pll;
 
+       pll->flags = RADEON_PLL_LEGACY;
+       if (radeon_new_pll == 1)
+               pll->algo = PLL_ALGO_NEW;
+       else
+               pll->algo = PLL_ALGO_LEGACY;
+
        if (mode->clock > 200000) /* range limits??? */
-               pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+               pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
        else
-               pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+               pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->crtc == crtc) {
@@ -782,20 +736,22 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                        }
 
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
-                               pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+                               pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
                        if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
-                               struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-                               struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
-                               if (lvds) {
-                                       if (lvds->use_bios_dividers) {
-                                               pll_ref_div = lvds->panel_ref_divider;
-                                               pll_fb_post_div   = (lvds->panel_fb_divider |
-                                                                    (lvds->panel_post_divider << 16));
-                                               htotal_cntl  = 0;
-                                               use_bios_divs = true;
+                               if (!rdev->is_atom_bios) {
+                                       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+                                       struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
+                                       if (lvds) {
+                                               if (lvds->use_bios_dividers) {
+                                                       pll_ref_div = lvds->panel_ref_divider;
+                                                       pll_fb_post_div   = (lvds->panel_fb_divider |
+                                                                            (lvds->panel_post_divider << 16));
+                                                       htotal_cntl  = 0;
+                                                       use_bios_divs = true;
+                                               }
                                        }
                                }
-                               pll_flags |= RADEON_PLL_USE_REF_DIV;
+                               pll->flags |= RADEON_PLL_USE_REF_DIV;
                        }
                }
        }
@@ -805,8 +761,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        if (!use_bios_divs) {
                radeon_compute_pll(pll, mode->clock,
                                   &freq, &feedback_div, &frac_fb_div,
-                                  &reference_div, &post_divider,
-                                  pll_flags);
+                                  &reference_div, &post_divider);
 
                for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
                        if (post_div->divider == post_divider)
@@ -1016,6 +971,12 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
 {
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       /* adjust pm to upcoming mode change */
+       radeon_pm_compute_clocks(rdev);
+
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
@@ -1032,8 +993,9 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
        radeon_crtc_set_base(crtc, x, y, old_fb);
        radeon_set_crtc_timing(crtc, adjusted_mode);
        radeon_set_pll(crtc, adjusted_mode);
+       radeon_overscan_setup(crtc, adjusted_mode);
        if (radeon_crtc->crtc_id == 0) {
-               radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
+               radeon_legacy_rmx_mode_set(crtc, adjusted_mode);
        } else {
                if (radeon_crtc->rmx_type != RMX_OFF) {
                        /* FIXME: only first crtc has rmx what should we
@@ -1047,12 +1009,29 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
 
 static void radeon_crtc_prepare(struct drm_crtc *crtc)
 {
-       radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc *crtci;
+
+       /*
+       * The hardware wedges sometimes if you reconfigure one CRTC
+       * whilst another is running (see fdo bug #24611).
+       */
+       list_for_each_entry(crtci, &dev->mode_config.crtc_list, head)
+               radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_crtc_commit(struct drm_crtc *crtc)
 {
-       radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc *crtci;
+
+       /*
+       * Reenable the CRTCs that should be running.
+       */
+       list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
+               if (crtci->enabled)
+                       radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
+       }
 }
 
 static const struct drm_crtc_helper_funcs legacy_helper_funcs = {