Merge branch 'drm-core-next' of ../linux-2.6 into drm-next
authorDave Airlie <airlied@redhat.com>
Wed, 18 Nov 2009 00:09:55 +0000 (10:09 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 18 Nov 2009 00:09:55 +0000 (10:09 +1000)
42 files changed:
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/atombios.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r500_reg.h
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_blit.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_benchmark.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_pm.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_reg.h
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/ttm/ttm_tt.c

index 9c92461..dc8e374 100644 (file)
@@ -707,7 +707,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
 
                if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) {
                        mutex_lock(&dev->mode_config.mutex);
-                       ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set);
+                       ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
                        mutex_unlock(&dev->mode_config.mutex);
                        if (ret)
                                return ret;
index 09a2892..b5713ee 100644 (file)
@@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \
        radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
        rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
        r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
-       r600_blit_kms.o
+       r600_blit_kms.o radeon_pm.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 
index 5d40208..c11dddd 100644 (file)
@@ -2314,7 +2314,7 @@ typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT {
        UCHAR ucSS_Step;
        UCHAR ucSS_Delay;
        UCHAR ucSS_Id;
-       UCHAR ucRecommandedRef_Div;
+       UCHAR ucRecommendedRef_Div;
        UCHAR ucSS_Range;       /* it was reserved for V11 */
 } ATOM_SPREAD_SPECTRUM_ASSIGNMENT;
 
index 14fa970..c15287a 100644 (file)
 #include "atom.h"
 #include "atom-bits.h"
 
-/* evil but including atombios.h is much worse */
-bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
-                               SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
-                               int32_t *pixel_clock);
 static void atombios_overscan_setup(struct drm_crtc *crtc,
                                    struct drm_display_mode *mode,
                                    struct drm_display_mode *adjusted_mode)
@@ -248,18 +244,18 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
 
        switch (mode) {
        case DRM_MODE_DPMS_ON:
+               atombios_enable_crtc(crtc, 1);
                if (ASIC_IS_DCE3(rdev))
                        atombios_enable_crtc_memreq(crtc, 1);
-               atombios_enable_crtc(crtc, 1);
                atombios_blank_crtc(crtc, 0);
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                atombios_blank_crtc(crtc, 1);
-               atombios_enable_crtc(crtc, 0);
                if (ASIC_IS_DCE3(rdev))
                        atombios_enable_crtc_memreq(crtc, 0);
+               atombios_enable_crtc(crtc, 0);
                break;
        }
 
@@ -270,59 +266,147 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 static void
 atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
-                            SET_CRTC_USING_DTD_TIMING_PARAMETERS * crtc_param)
+                            struct drm_display_mode *mode)
 {
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
-       SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param;
+       SET_CRTC_USING_DTD_TIMING_PARAMETERS args;
        int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
+       u16 misc = 0;
 
-       conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size);
-       conv_param.usH_Blanking_Time =
-           cpu_to_le16(crtc_param->usH_Blanking_Time);
-       conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size);
-       conv_param.usV_Blanking_Time =
-           cpu_to_le16(crtc_param->usV_Blanking_Time);
-       conv_param.usH_SyncOffset = cpu_to_le16(crtc_param->usH_SyncOffset);
-       conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
-       conv_param.usV_SyncOffset = cpu_to_le16(crtc_param->usV_SyncOffset);
-       conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
-       conv_param.susModeMiscInfo.usAccess =
-           cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
-       conv_param.ucCRTC = crtc_param->ucCRTC;
+       memset(&args, 0, sizeof(args));
+       args.usH_Size = cpu_to_le16(mode->crtc_hdisplay);
+       args.usH_Blanking_Time =
+               cpu_to_le16(mode->crtc_hblank_end - mode->crtc_hdisplay);
+       args.usV_Size = cpu_to_le16(mode->crtc_vdisplay);
+       args.usV_Blanking_Time =
+           cpu_to_le16(mode->crtc_vblank_end - mode->crtc_vdisplay);
+       args.usH_SyncOffset =
+               cpu_to_le16(mode->crtc_hsync_start - mode->crtc_hdisplay);
+       args.usH_SyncWidth =
+               cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
+       args.usV_SyncOffset =
+               cpu_to_le16(mode->crtc_vsync_start - mode->crtc_vdisplay);
+       args.usV_SyncWidth =
+               cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
+       /*args.ucH_Border = mode->hborder;*/
+       /*args.ucV_Border = mode->vborder;*/
+
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               misc |= ATOM_VSYNC_POLARITY;
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               misc |= ATOM_HSYNC_POLARITY;
+       if (mode->flags & DRM_MODE_FLAG_CSYNC)
+               misc |= ATOM_COMPOSITESYNC;
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               misc |= ATOM_INTERLACE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_DOUBLE_CLOCK_MODE;
+
+       args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
+       args.ucCRTC = radeon_crtc->crtc_id;
 
        printk("executing set crtc dtd timing\n");
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-void atombios_crtc_set_timing(struct drm_crtc *crtc,
-                             SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *
-                             crtc_param)
+static void atombios_crtc_set_timing(struct drm_crtc *crtc,
+                                    struct drm_display_mode *mode)
 {
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
-       SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param;
+       SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
+       u16 misc = 0;
 
-       conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total);
-       conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp);
-       conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart);
-       conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
-       conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total);
-       conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp);
-       conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart);
-       conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
-       conv_param.susModeMiscInfo.usAccess =
-           cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
-       conv_param.ucCRTC = crtc_param->ucCRTC;
-       conv_param.ucOverscanRight = crtc_param->ucOverscanRight;
-       conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft;
-       conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom;
-       conv_param.ucOverscanTop = crtc_param->ucOverscanTop;
-       conv_param.ucReserved = crtc_param->ucReserved;
+       memset(&args, 0, sizeof(args));
+       args.usH_Total = cpu_to_le16(mode->crtc_htotal);
+       args.usH_Disp = cpu_to_le16(mode->crtc_hdisplay);
+       args.usH_SyncStart = cpu_to_le16(mode->crtc_hsync_start);
+       args.usH_SyncWidth =
+               cpu_to_le16(mode->crtc_hsync_end - mode->crtc_hsync_start);
+       args.usV_Total = cpu_to_le16(mode->crtc_vtotal);
+       args.usV_Disp = cpu_to_le16(mode->crtc_vdisplay);
+       args.usV_SyncStart = cpu_to_le16(mode->crtc_vsync_start);
+       args.usV_SyncWidth =
+               cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start);
+
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               misc |= ATOM_VSYNC_POLARITY;
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               misc |= ATOM_HSYNC_POLARITY;
+       if (mode->flags & DRM_MODE_FLAG_CSYNC)
+               misc |= ATOM_COMPOSITESYNC;
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               misc |= ATOM_INTERLACE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_DOUBLE_CLOCK_MODE;
+
+       args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
+       args.ucCRTC = radeon_crtc->crtc_id;
 
        printk("executing set crtc timing\n");
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void atombios_set_ss(struct drm_crtc *crtc, int enable)
+{
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_encoder *encoder = NULL;
+       struct radeon_encoder *radeon_encoder = NULL;
+       struct radeon_encoder_atom_dig *dig = NULL;
+       int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
+       ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args;
+       ENABLE_LVDS_SS_PARAMETERS legacy_args;
+       uint16_t percentage = 0;
+       uint8_t type = 0, step = 0, delay = 0, range = 0;
+
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               if (encoder->crtc == crtc) {
+                       radeon_encoder = to_radeon_encoder(encoder);
+                       /* only enable spread spectrum on LVDS */
+                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                               dig = radeon_encoder->enc_priv;
+                               if (dig && dig->ss) {
+                                       percentage = dig->ss->percentage;
+                                       type = dig->ss->type;
+                                       step = dig->ss->step;
+                                       delay = dig->ss->delay;
+                                       range = dig->ss->range;
+                               } else if (enable)
+                                       return;
+                       } else if (enable)
+                               return;
+                       break;
+               }
+       }
+
+       if (!radeon_encoder)
+               return;
+
+       if (ASIC_IS_AVIVO(rdev)) {
+               memset(&args, 0, sizeof(args));
+               args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
+               args.ucSpreadSpectrumType = type;
+               args.ucSpreadSpectrumStep = step;
+               args.ucSpreadSpectrumDelay = delay;
+               args.ucSpreadSpectrumRange = range;
+               args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+               args.ucEnable = enable;
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+       } else {
+               memset(&legacy_args, 0, sizeof(legacy_args));
+               legacy_args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
+               legacy_args.ucSpreadSpectrumType = type;
+               legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
+               legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
+               legacy_args.ucEnable = enable;
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args);
+       }
 }
 
 void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
@@ -333,12 +417,13 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        struct drm_encoder *encoder = NULL;
        struct radeon_encoder *radeon_encoder = NULL;
        uint8_t frev, crev;
-       int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
+       int index;
        SET_PIXEL_CLOCK_PS_ALLOCATION args;
        PIXEL_CLOCK_PARAMETERS *spc1_ptr;
        PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
        PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
-       uint32_t sclock = mode->clock;
+       uint32_t pll_clock = mode->clock;
+       uint32_t adjusted_clock;
        uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
        struct radeon_pll *pll;
        int pll_flags = 0;
@@ -346,8 +431,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        memset(&args, 0, sizeof(args));
 
        if (ASIC_IS_AVIVO(rdev)) {
-               uint32_t ss_cntl;
-
                if ((rdev->family == CHIP_RS600) ||
                    (rdev->family == CHIP_RS690) ||
                    (rdev->family == CHIP_RS740))
@@ -358,15 +441,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                        pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
                else
                        pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
-
-               /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
-               if (radeon_crtc->crtc_id == 0) {
-                       ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
-                       WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1);
-               } else {
-                       ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
-                       WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1);
-               }
        } else {
                pll_flags |= RADEON_PLL_LEGACY;
 
@@ -393,14 +467,43 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                }
        }
 
+       /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
+        * accordingly based on the encoder/transmitter to work around
+        * special hw requirements.
+        */
+       if (ASIC_IS_DCE3(rdev)) {
+               ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
+
+               if (!encoder)
+                       return;
+
+               memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
+               adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
+               adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
+               adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
+
+               index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
+               atom_execute_table(rdev->mode_info.atom_context,
+                                  index, (uint32_t *)&adjust_pll_args);
+               adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
+       } else {
+               /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
+               if (ASIC_IS_AVIVO(rdev) &&
+                   (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
+                       adjusted_clock = mode->clock * 2;
+               else
+                       adjusted_clock = mode->clock;
+       }
+
        if (radeon_crtc->crtc_id == 0)
                pll = &rdev->clock.p1pll;
        else
                pll = &rdev->clock.p2pll;
 
-       radeon_compute_pll(pll, mode->clock, &sclock, &fb_div, &frac_fb_div,
+       radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
                           &ref_div, &post_div, pll_flags);
 
+       index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
        atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
                              &crev);
 
@@ -409,7 +512,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                switch (crev) {
                case 1:
                        spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
-                       spc1_ptr->usPixelClock = cpu_to_le16(sclock);
+                       spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
                        spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
                        spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
                        spc1_ptr->ucFracFbDiv = frac_fb_div;
@@ -422,7 +525,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                case 2:
                        spc2_ptr =
                            (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
-                       spc2_ptr->usPixelClock = cpu_to_le16(sclock);
+                       spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
                        spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
                        spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
                        spc2_ptr->ucFracFbDiv = frac_fb_div;
@@ -437,7 +540,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
                                return;
                        spc3_ptr =
                            (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
-                       spc3_ptr->usPixelClock = cpu_to_le16(sclock);
+                       spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
                        spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
                        spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
                        spc3_ptr->ucFracFbDiv = frac_fb_div;
@@ -527,6 +630,16 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                WREG32(AVIVO_D1VGA_CONTROL, 0);
        else
                WREG32(AVIVO_D2VGA_CONTROL, 0);
+
+       if (rdev->family >= CHIP_RV770) {
+               if (radeon_crtc->crtc_id) {
+                       WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
+                       WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
+               } else {
+                       WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
+                       WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
+               }
+       }
        WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
               (u32) fb_location);
        WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
@@ -563,6 +676,10 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                radeon_fb = to_radeon_framebuffer(old_fb);
                radeon_gem_object_unpin(radeon_fb->obj);
        }
+
+       /* Bytes per pixel may have changed */
+       radeon_bandwidth_update(rdev);
+
        return 0;
 }
 
@@ -574,134 +691,24 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
-       struct drm_encoder *encoder;
-       SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
-       int need_tv_timings = 0;
-       bool ret;
 
        /* TODO color tiling */
-       memset(&crtc_timing, 0, sizeof(crtc_timing));
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               /* find tv std */
-               if (encoder->crtc == crtc) {
-                       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-
-                       if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
-                               struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
-                               if (tv_dac) {
-                                       if (tv_dac->tv_std == TV_STD_NTSC ||
-                                           tv_dac->tv_std == TV_STD_NTSC_J ||
-                                           tv_dac->tv_std == TV_STD_PAL_M)
-                                               need_tv_timings = 1;
-                                       else
-                                               need_tv_timings = 2;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       crtc_timing.ucCRTC = radeon_crtc->crtc_id;
-       if (need_tv_timings) {
-               ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1,
-                                                &crtc_timing, &adjusted_mode->clock);
-               if (ret == false)
-                       need_tv_timings = 0;
-       }
-
-       if (!need_tv_timings) {
-               crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
-               crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
-               crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
-               crtc_timing.usH_SyncWidth =
-                       adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
-
-               crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
-               crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
-               crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
-               crtc_timing.usV_SyncWidth =
-                       adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
-
-               if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-                       crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
-
-               if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-                       crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
-
-               if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
-                       crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
-
-               if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
-                       crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
-
-               if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-                       crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
-       }
 
+       atombios_set_ss(crtc, 0);
        atombios_crtc_set_pll(crtc, adjusted_mode);
-       atombios_crtc_set_timing(crtc, &crtc_timing);
+       atombios_set_ss(crtc, 1);
+       atombios_crtc_set_timing(crtc, adjusted_mode);
 
        if (ASIC_IS_AVIVO(rdev))
                atombios_crtc_set_base(crtc, x, y, old_fb);
        else {
-               if (radeon_crtc->crtc_id == 0) {
-                       SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
-                       memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
-
-                       /* setup FP shadow regs on R4xx */
-                       crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
-                       crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay;
-                       crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay;
-                       crtc_dtd_timing.usH_Blanking_Time =
-                           adjusted_mode->crtc_hblank_end -
-                           adjusted_mode->crtc_hdisplay;
-                       crtc_dtd_timing.usV_Blanking_Time =
-                           adjusted_mode->crtc_vblank_end -
-                           adjusted_mode->crtc_vdisplay;
-                       crtc_dtd_timing.usH_SyncOffset =
-                           adjusted_mode->crtc_hsync_start -
-                           adjusted_mode->crtc_hdisplay;
-                       crtc_dtd_timing.usV_SyncOffset =
-                           adjusted_mode->crtc_vsync_start -
-                           adjusted_mode->crtc_vdisplay;
-                       crtc_dtd_timing.usH_SyncWidth =
-                           adjusted_mode->crtc_hsync_end -
-                           adjusted_mode->crtc_hsync_start;
-                       crtc_dtd_timing.usV_SyncWidth =
-                           adjusted_mode->crtc_vsync_end -
-                           adjusted_mode->crtc_vsync_start;
-                       /* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */
-                       /* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */
-
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-                               crtc_dtd_timing.susModeMiscInfo.usAccess |=
-                                   ATOM_VSYNC_POLARITY;
-
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-                               crtc_dtd_timing.susModeMiscInfo.usAccess |=
-                                   ATOM_HSYNC_POLARITY;
-
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
-                               crtc_dtd_timing.susModeMiscInfo.usAccess |=
-                                   ATOM_COMPOSITESYNC;
-
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
-                               crtc_dtd_timing.susModeMiscInfo.usAccess |=
-                                   ATOM_INTERLACE;
-
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-                               crtc_dtd_timing.susModeMiscInfo.usAccess |=
-                                   ATOM_DOUBLE_CLOCK_MODE;
-
-                       atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing);
-               }
+               if (radeon_crtc->crtc_id == 0)
+                       atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
                radeon_crtc_set_base(crtc, x, y, old_fb);
                radeon_legacy_atom_set_surface(crtc);
        }
        atombios_overscan_setup(crtc, mode, adjusted_mode);
        atombios_scaler_setup(crtc);
-       radeon_bandwidth_update(rdev);
        return 0;
 }
 
index 161094c..c9e93ea 100644 (file)
@@ -186,7 +186,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
 
 int r100_irq_process(struct radeon_device *rdev)
 {
-       uint32_t status;
+       uint32_t status, msi_rearm;
 
        status = r100_irq_ack(rdev);
        if (!status) {
@@ -209,6 +209,21 @@ int r100_irq_process(struct radeon_device *rdev)
                }
                status = r100_irq_ack(rdev);
        }
+       if (rdev->msi_enabled) {
+               switch (rdev->family) {
+               case CHIP_RS400:
+               case CHIP_RS480:
+                       msi_rearm = RREG32(RADEON_AIC_CNTL) & ~RS400_MSI_REARM;
+                       WREG32(RADEON_AIC_CNTL, msi_rearm);
+                       WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM);
+                       break;
+               default:
+                       msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm);
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+                       break;
+               }
+       }
        return IRQ_HANDLED;
 }
 
@@ -240,7 +255,7 @@ int r100_wb_init(struct radeon_device *rdev)
        int r;
 
        if (rdev->wb.wb_obj == NULL) {
-               r = radeon_object_create(rdev, NULL, 4096,
+               r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
                                         true,
                                         RADEON_GEM_DOMAIN_GTT,
                                         false, &rdev->wb.wb_obj);
@@ -563,19 +578,19 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        indirect1_start = 16;
        /* cp setup */
        WREG32(0x718, pre_write_timer | (pre_write_limit << 28));
-       WREG32(RADEON_CP_RB_CNTL,
-#ifdef __BIG_ENDIAN
-              RADEON_BUF_SWAP_32BIT |
-#endif
-              REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
+       tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
               REG_SET(RADEON_RB_BLKSZ, rb_blksz) |
               REG_SET(RADEON_MAX_FETCH, max_fetch) |
               RADEON_RB_NO_UPDATE);
+#ifdef __BIG_ENDIAN
+       tmp |= RADEON_BUF_SWAP_32BIT;
+#endif
+       WREG32(RADEON_CP_RB_CNTL, tmp);
+
        /* Set ring address */
        DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr);
        WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr);
        /* Force read & write ptr to 0 */
-       tmp = RREG32(RADEON_CP_RB_CNTL);
        WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
        WREG32(RADEON_CP_RB_RPTR_WR, 0);
        WREG32(RADEON_CP_RB_WPTR, 0);
@@ -2364,7 +2379,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
        /*
          Find the total latency for the display data.
        */
-       disp_latency_overhead.full = rfixed_const(80);
+       disp_latency_overhead.full = rfixed_const(8);
        disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
        mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
        mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
@@ -2562,8 +2577,11 @@ void r100_bandwidth_update(struct radeon_device *rdev)
 static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
 {
        DRM_ERROR("pitch                      %d\n", t->pitch);
+       DRM_ERROR("use_pitch                  %d\n", t->use_pitch);
        DRM_ERROR("width                      %d\n", t->width);
+       DRM_ERROR("width_11                   %d\n", t->width_11);
        DRM_ERROR("height                     %d\n", t->height);
+       DRM_ERROR("height_11                  %d\n", t->height_11);
        DRM_ERROR("num levels                 %d\n", t->num_levels);
        DRM_ERROR("depth                      %d\n", t->txdepth);
        DRM_ERROR("bpp                        %d\n", t->cpp);
@@ -2623,15 +2641,17 @@ static int r100_cs_track_texture_check(struct radeon_device *rdev,
                                else
                                        w = track->textures[u].pitch / (1 << i);
                        } else {
-                               w = track->textures[u].width / (1 << i);
+                               w = track->textures[u].width;
                                if (rdev->family >= CHIP_RV515)
                                        w |= track->textures[u].width_11;
+                               w = w / (1 << i);
                                if (track->textures[u].roundup_w)
                                        w = roundup_pow_of_two(w);
                        }
-                       h = track->textures[u].height / (1 << i);
+                       h = track->textures[u].height;
                        if (rdev->family >= CHIP_RV515)
                                h |= track->textures[u].height_11;
+                       h = h / (1 << i);
                        if (track->textures[u].roundup_h)
                                h = roundup_pow_of_two(h);
                        size += w * h;
index e08c4a8..2f43ee8 100644 (file)
@@ -113,7 +113,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
        tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
        WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
        WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location);
-       tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 4096;
+       tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - RADEON_GPU_PAGE_SIZE;
        WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
        WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
        WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
index 5c7fe52..1cefdbc 100644 (file)
@@ -311,6 +311,8 @@ int r420_init(struct radeon_device *rdev)
        }
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Get vram informations */
        r300_vram_info(rdev);
        /* Initialize memory controller (also test AGP) */
index 868add6..7baa739 100644 (file)
 #       define AVIVO_D1GRPH_TILED                               (1 << 20)
 #       define AVIVO_D1GRPH_MACRO_ADDRESS_MODE                  (1 << 21)
 
+/* The R7xx *_HIGH surface regs are backwards; the D1 regs are in the D2
+ * block and vice versa.  This applies to GRPH, CUR, etc.
+ */
 #define AVIVO_D1GRPH_LUT_SEL                                    0x6108
 #define AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS                    0x6110
+#define R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                0x6914
+#define R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                0x6114
 #define AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS                  0x6118
+#define R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH              0x691c
+#define R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH              0x611c
 #define AVIVO_D1GRPH_PITCH                                      0x6120
 #define AVIVO_D1GRPH_SURFACE_OFFSET_X                           0x6124
 #define AVIVO_D1GRPH_SURFACE_OFFSET_Y                           0x6128
 #       define AVIVO_D1CURSOR_MODE_MASK         (3 << 8)
 #       define AVIVO_D1CURSOR_MODE_24BPP        2
 #define AVIVO_D1CUR_SURFACE_ADDRESS             0x6408
+#define R700_D1CUR_SURFACE_ADDRESS_HIGH         0x6c0c
+#define R700_D2CUR_SURFACE_ADDRESS_HIGH         0x640c
 #define AVIVO_D1CUR_SIZE                        0x6410
 #define AVIVO_D1CUR_POSITION                    0x6414
 #define AVIVO_D1CUR_HOT_SPOT                    0x6418
index a555b7b..f743518 100644 (file)
@@ -260,6 +260,8 @@ int r520_init(struct radeon_device *rdev)
        }
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Get vram informations */
        r520_vram_info(rdev);
        /* Initialize memory controller (also test AGP) */
index 6097194..278f646 100644 (file)
@@ -339,11 +339,10 @@ int r600_mc_init(struct radeon_device *rdev)
 {
        fixed20_12 a;
        u32 tmp;
-       int chansize;
+       int chansize, numchan;
        int r;
 
        /* Get VRAM informations */
-       rdev->mc.vram_width = 128;
        rdev->mc.vram_is_ddr = true;
        tmp = RREG32(RAMCFG);
        if (tmp & CHANSIZE_OVERRIDE) {
@@ -353,17 +352,23 @@ int r600_mc_init(struct radeon_device *rdev)
        } else {
                chansize = 32;
        }
-       if (rdev->family == CHIP_R600) {
-               rdev->mc.vram_width = 8 * chansize;
-       } else if (rdev->family == CHIP_RV670) {
-               rdev->mc.vram_width = 4 * chansize;
-       } else if ((rdev->family == CHIP_RV610) ||
-                       (rdev->family == CHIP_RV620)) {
-               rdev->mc.vram_width = chansize;
-       } else if ((rdev->family == CHIP_RV630) ||
-                       (rdev->family == CHIP_RV635)) {
-               rdev->mc.vram_width = 2 * chansize;
+       tmp = RREG32(CHMAP);
+       switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+       case 0:
+       default:
+               numchan = 1;
+               break;
+       case 1:
+               numchan = 2;
+               break;
+       case 2:
+               numchan = 4;
+               break;
+       case 3:
+               numchan = 8;
+               break;
        }
+       rdev->mc.vram_width = numchan * chansize;
        /* Could aper size report 0 ? */
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
        rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
@@ -404,35 +409,29 @@ int r600_mc_init(struct radeon_device *rdev)
                        rdev->mc.gtt_location = rdev->mc.mc_vram_size;
                }
        } else {
-               if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
-                       rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) &
-                                                               0xFFFF) << 24;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-                       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
-                       if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
-                               /* Enough place after vram */
-                               rdev->mc.gtt_location = tmp;
-                       } else if (rdev->mc.vram_location >= rdev->mc.gtt_size) {
-                               /* Enough place before vram */
+               rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+               rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) &
+                                                       0xFFFF) << 24;
+               tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
+               if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
+                       /* Enough place after vram */
+                       rdev->mc.gtt_location = tmp;
+               } else if (rdev->mc.vram_location >= rdev->mc.gtt_size) {
+                       /* Enough place before vram */
+                       rdev->mc.gtt_location = 0;
+               } else {
+                       /* Not enough place after or before shrink
+                        * gart size
+                        */
+                       if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) {
                                rdev->mc.gtt_location = 0;
+                               rdev->mc.gtt_size = rdev->mc.vram_location;
                        } else {
-                               /* Not enough place after or before shrink
-                                * gart size
-                                */
-                               if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) {
-                                       rdev->mc.gtt_location = 0;
-                                       rdev->mc.gtt_size = rdev->mc.vram_location;
-                               } else {
-                                       rdev->mc.gtt_location = tmp;
-                                       rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp;
-                               }
+                               rdev->mc.gtt_location = tmp;
+                               rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp;
                        }
-                       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-               } else {
-                       rdev->mc.vram_location = 0x00000000UL;
-                       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
                }
+               rdev->mc.gtt_location = rdev->mc.mc_vram_size;
        }
        rdev->mc.vram_start = rdev->mc.vram_location;
        rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
@@ -859,7 +858,8 @@ void r600_gpu_init(struct radeon_device *rdev)
            ((rdev->family) == CHIP_RV630) ||
            ((rdev->family) == CHIP_RV610) ||
            ((rdev->family) == CHIP_RV620) ||
-           ((rdev->family) == CHIP_RS780)) {
+           ((rdev->family) == CHIP_RS780) ||
+           ((rdev->family) == CHIP_RS880)) {
                WREG32(DB_DEBUG, PREZ_MUST_WAIT_FOR_POSTZ_DONE);
        } else {
                WREG32(DB_DEBUG, 0);
@@ -876,7 +876,8 @@ void r600_gpu_init(struct radeon_device *rdev)
        tmp = RREG32(SQ_MS_FIFO_SIZES);
        if (((rdev->family) == CHIP_RV610) ||
            ((rdev->family) == CHIP_RV620) ||
-           ((rdev->family) == CHIP_RS780)) {
+           ((rdev->family) == CHIP_RS780) ||
+           ((rdev->family) == CHIP_RS880)) {
                tmp = (CACHE_FIFO_SIZE(0xa) |
                       FETCH_FIFO_HIWATER(0xa) |
                       DONE_FIFO_HIWATER(0xe0) |
@@ -919,7 +920,8 @@ void r600_gpu_init(struct radeon_device *rdev)
                                            NUM_ES_STACK_ENTRIES(0));
        } else if (((rdev->family) == CHIP_RV610) ||
                   ((rdev->family) == CHIP_RV620) ||
-                  ((rdev->family) == CHIP_RS780)) {
+                  ((rdev->family) == CHIP_RS780) ||
+                  ((rdev->family) == CHIP_RS880)) {
                /* no vertex cache */
                sq_config &= ~VC_ENABLE;
 
@@ -976,7 +978,8 @@ void r600_gpu_init(struct radeon_device *rdev)
 
        if (((rdev->family) == CHIP_RV610) ||
            ((rdev->family) == CHIP_RV620) ||
-           ((rdev->family) == CHIP_RS780)) {
+           ((rdev->family) == CHIP_RS780) ||
+           ((rdev->family) == CHIP_RS880)) {
                WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(TC_ONLY));
        } else {
                WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC));
@@ -1002,8 +1005,9 @@ void r600_gpu_init(struct radeon_device *rdev)
        tmp = rdev->config.r600.max_pipes * 16;
        switch (rdev->family) {
        case CHIP_RV610:
-       case CHIP_RS780:
        case CHIP_RV620:
+       case CHIP_RS780:
+       case CHIP_RS880:
                tmp += 32;
                break;
        case CHIP_RV670:
@@ -1044,8 +1048,9 @@ void r600_gpu_init(struct radeon_device *rdev)
 
        switch (rdev->family) {
        case CHIP_RV610:
-       case CHIP_RS780:
        case CHIP_RV620:
+       case CHIP_RS780:
+       case CHIP_RS880:
                tmp = TC_L2_SIZE(8);
                break;
        case CHIP_RV630:
@@ -1267,19 +1272,17 @@ int r600_cp_resume(struct radeon_device *rdev)
 
        /* Set ring buffer size */
        rb_bufsz = drm_order(rdev->cp.ring_size / 8);
+       tmp = RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
 #ifdef __BIG_ENDIAN
-       WREG32(CP_RB_CNTL, BUF_SWAP_32BIT | RB_NO_UPDATE |
-               (drm_order(4096/8) << 8) | rb_bufsz);
-#else
-       WREG32(CP_RB_CNTL, RB_NO_UPDATE | (drm_order(4096/8) << 8) | rb_bufsz);
+       tmp |= BUF_SWAP_32BIT;
 #endif
+       WREG32(CP_RB_CNTL, tmp);
        WREG32(CP_SEM_WAIT_TIMER, 0x4);
 
        /* Set the write pointer delay */
        WREG32(CP_RB_WPTR_DELAY, 0);
 
        /* Initialize the ring buffer's read and write pointers */
-       tmp = RREG32(CP_RB_CNTL);
        WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA);
        WREG32(CP_RB_RPTR_WR, 0);
        WREG32(CP_RB_WPTR, 0);
@@ -1400,7 +1403,7 @@ int r600_wb_enable(struct radeon_device *rdev)
        int r;
 
        if (rdev->wb.wb_obj == NULL) {
-               r = radeon_object_create(rdev, NULL, 4096, true,
+               r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
                                RADEON_GEM_DOMAIN_GTT, false, &rdev->wb.wb_obj);
                if (r) {
                        dev_warn(rdev->dev, "failed to create WB buffer (%d).\n", r);
@@ -1450,8 +1453,8 @@ int r600_copy_blit(struct radeon_device *rdev,
                   uint64_t src_offset, uint64_t dst_offset,
                   unsigned num_pages, struct radeon_fence *fence)
 {
-       r600_blit_prepare_copy(rdev, num_pages * 4096);
-       r600_kms_blit_copy(rdev, src_offset, dst_offset, num_pages * 4096);
+       r600_blit_prepare_copy(rdev, num_pages * RADEON_GPU_PAGE_SIZE);
+       r600_kms_blit_copy(rdev, src_offset, dst_offset, num_pages * RADEON_GPU_PAGE_SIZE);
        r600_blit_done_copy(rdev, fence);
        return 0;
 }
@@ -1632,10 +1635,13 @@ int r600_init(struct radeon_device *rdev)
        r600_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        r = radeon_clocks_init(rdev);
        if (r)
                return r;
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
        if (r)
index dec5010..5ea4323 100644 (file)
@@ -582,6 +582,8 @@ r600_blit_copy(struct drm_device *dev,
        u64 vb_addr;
        u32 *vb;
 
+       vb = r600_nomm_get_vb_ptr(dev);
+
        if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
                max_bytes = 8192;
 
@@ -617,8 +619,8 @@ r600_blit_copy(struct drm_device *dev,
                                if (!dev_priv->blit_vb)
                                        return;
                                set_shaders(dev);
+                               vb = r600_nomm_get_vb_ptr(dev);
                        }
-                       vb = r600_nomm_get_vb_ptr(dev);
 
                        vb[0] = i2f(dst_x);
                        vb[1] = 0;
@@ -706,8 +708,8 @@ r600_blit_copy(struct drm_device *dev,
                                        return;
 
                                set_shaders(dev);
+                               vb = r600_nomm_get_vb_ptr(dev);
                        }
-                       vb = r600_nomm_get_vb_ptr(dev);
 
                        vb[0] = i2f(dst_x / 4);
                        vb[1] = 0;
@@ -772,6 +774,7 @@ r600_blit_swap(struct drm_device *dev,
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        int cb_format, tex_format;
+       int sx2, sy2, dx2, dy2;
        u64 vb_addr;
        u32 *vb;
 
@@ -786,16 +789,10 @@ r600_blit_swap(struct drm_device *dev,
        }
        vb = r600_nomm_get_vb_ptr(dev);
 
-       if (cpp == 4) {
-               cb_format = COLOR_8_8_8_8;
-               tex_format = FMT_8_8_8_8;
-       } else if (cpp == 2) {
-               cb_format = COLOR_5_6_5;
-               tex_format = FMT_5_6_5;
-       } else {
-               cb_format = COLOR_8;
-               tex_format = FMT_8;
-       }
+       sx2 = sx + w;
+       sy2 = sy + h;
+       dx2 = dx + w;
+       dy2 = dy + h;
 
        vb[0] = i2f(dx);
        vb[1] = i2f(dy);
@@ -803,31 +800,46 @@ r600_blit_swap(struct drm_device *dev,
        vb[3] = i2f(sy);
 
        vb[4] = i2f(dx);
-       vb[5] = i2f(dy + h);
+       vb[5] = i2f(dy2);
        vb[6] = i2f(sx);
-       vb[7] = i2f(sy + h);
+       vb[7] = i2f(sy2);
+
+       vb[8] = i2f(dx2);
+       vb[9] = i2f(dy2);
+       vb[10] = i2f(sx2);
+       vb[11] = i2f(sy2);
 
-       vb[8] = i2f(dx + w);
-       vb[9] = i2f(dy + h);
-       vb[10] = i2f(sx + w);
-       vb[11] = i2f(sy + h);
+       switch(cpp) {
+       case 4:
+               cb_format = COLOR_8_8_8_8;
+               tex_format = FMT_8_8_8_8;
+               break;
+       case 2:
+               cb_format = COLOR_5_6_5;
+               tex_format = FMT_5_6_5;
+               break;
+       default:
+               cb_format = COLOR_8;
+               tex_format = FMT_8;
+               break;
+       }
 
        /* src */
        set_tex_resource(dev_priv, tex_format,
                         src_pitch / cpp,
-                        sy + h, src_pitch / cpp,
+                        sy2, src_pitch / cpp,
                         src_gpu_addr);
 
        cp_set_surface_sync(dev_priv,
-                           R600_TC_ACTION_ENA, (src_pitch * (sy + h)), src_gpu_addr);
+                           R600_TC_ACTION_ENA, src_pitch * sy2, src_gpu_addr);
 
        /* dst */
        set_render_target(dev_priv, cb_format,
-                         dst_pitch / cpp, dy + h,
+                         dst_pitch / cpp, dy2,
                          dst_gpu_addr);
 
        /* scissors */
-       set_scissors(dev_priv, dx, dy, dx + w, dy + h);
+       set_scissors(dev_priv, dx, dy, dx2, dy2);
 
        /* Vertex buffer setup */
        vb_addr = dev_priv->gart_buffers_offset +
@@ -840,7 +852,7 @@ r600_blit_swap(struct drm_device *dev,
 
        cp_set_surface_sync(dev_priv,
                            R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
-                           dst_pitch * (dy + h), dst_gpu_addr);
+                           dst_pitch * dy2, dst_gpu_addr);
 
        dev_priv->blit_vb->used += 12 * 4;
 }
index 93108bb..dbf716e 100644 (file)
@@ -368,7 +368,7 @@ set_default_state(struct radeon_device *rdev)
        if ((rdev->family == CHIP_RV610) ||
            (rdev->family == CHIP_RV620) ||
            (rdev->family == CHIP_RS780) ||
-           (rdev->family == CHIP_RS780) ||
+           (rdev->family == CHIP_RS880) ||
            (rdev->family == CHIP_RV710))
                sq_config = 0;
        else
@@ -610,6 +610,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
 
        DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
                  size_bytes, rdev->r600_blit.vb_used);
+       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
        if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
                max_bytes = 8192;
 
@@ -652,7 +653,6 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
                                vb = r600_nomm_get_vb_ptr(dev);
 #endif
                        }
-                       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
 
                        vb[0] = i2f(dst_x);
                        vb[1] = 0;
@@ -747,7 +747,6 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
                                vb = r600_nomm_get_vb_ptr(dev);
                        }
 #endif
-                       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
 
                        vb[0] = i2f(dst_x / 4);
                        vb[1] = 0;
index 9b64d47..00d9642 100644 (file)
 #define        PCIE_PORT_INDEX                                 0x0038
 #define        PCIE_PORT_DATA                                  0x003C
 
+#define CHMAP                                          0x2004
+#define                NOOFCHAN_SHIFT                                  12
+#define                NOOFCHAN_MASK                                   0x00003000
+
 #define RAMCFG                                         0x2408
 #define                NOOFBANK_SHIFT                                  0
 #define                NOOFBANK_MASK                                   0x00000001
index 5ab35b8..757f5cd 100644 (file)
@@ -139,6 +139,10 @@ struct radeon_clock {
        uint32_t default_sclk;
 };
 
+/*
+ * Power management
+ */
+int radeon_pm_init(struct radeon_device *rdev);
 
 /*
  * Fences.
@@ -276,6 +280,8 @@ union radeon_gart_table {
        struct radeon_gart_table_vram   vram;
 };
 
+#define RADEON_GPU_PAGE_SIZE 4096
+
 struct radeon_gart {
        dma_addr_t                      table_addr;
        unsigned                        num_gpu_pages;
@@ -621,7 +627,9 @@ struct radeon_asic {
                    uint64_t dst_offset,
                    unsigned num_pages,
                    struct radeon_fence *fence);
+       uint32_t (*get_engine_clock)(struct radeon_device *rdev);
        void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock);
+       uint32_t (*get_memory_clock)(struct radeon_device *rdev);
        void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
        void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
        void (*set_clock_gating)(struct radeon_device *rdev, int enable);
@@ -783,6 +791,7 @@ struct radeon_device {
        const struct firmware *me_fw;   /* all family ME firmware */
        const struct firmware *pfp_fw;  /* r6/700 PFP firmware */
        struct r600_blit r600_blit;
+       int msi_enabled; /* msi enabled */
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -952,7 +961,9 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 #define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
 #define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
 #define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy((rdev), (s), (d), (np), (f))
+#define radeon_get_engine_clock(rdev) (rdev)->asic->get_engine_clock((rdev))
 #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
+#define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev))
 #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
 #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
 #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
index c3532c7..c18fbee 100644 (file)
 /*
  * common functions
  */
+uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev);
 void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
 void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
 
+uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev);
 void radeon_atom_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
+uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev);
 void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock);
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 
@@ -95,7 +98,9 @@ static struct radeon_asic r100_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = NULL,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = NULL,
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@ -148,7 +153,9 @@ static struct radeon_asic r300_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = NULL,
        .set_memory_clock = NULL,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@ -185,7 +192,9 @@ static struct radeon_asic r420_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@ -227,7 +236,9 @@ static struct radeon_asic rs400_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_legacy_get_engine_clock,
        .set_engine_clock = &radeon_legacy_set_engine_clock,
+       .get_memory_clock = NULL,
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
@@ -273,7 +284,9 @@ static struct radeon_asic rs600_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@ -312,7 +325,9 @@ static struct radeon_asic rs690_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r300_copy_dma,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@ -357,7 +372,9 @@ static struct radeon_asic rv515_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@ -393,7 +410,9 @@ static struct radeon_asic r520_asic = {
        .copy_blit = &r100_copy_blit,
        .copy_dma = &r300_copy_dma,
        .copy = &r100_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@ -456,7 +475,9 @@ static struct radeon_asic r600_asic = {
        .copy_blit = &r600_copy_blit,
        .copy_dma = &r600_copy_blit,
        .copy = &r600_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
@@ -493,7 +514,9 @@ static struct radeon_asic rv770_asic = {
        .copy_blit = &r600_copy_blit,
        .copy_dma = &r600_copy_blit,
        .copy = &r600_copy_blit,
+       .get_engine_clock = &radeon_atom_get_engine_clock,
        .set_engine_clock = &radeon_atom_set_engine_clock,
+       .get_memory_clock = &radeon_atom_get_memory_clock,
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
index 5b6c08c..2ed88a8 100644 (file)
@@ -46,7 +46,8 @@ radeon_add_atom_connector(struct drm_device *dev,
                          uint32_t supported_device,
                          int connector_type,
                          struct radeon_i2c_bus_rec *i2c_bus,
-                         bool linkb, uint32_t igp_lane_info);
+                         bool linkb, uint32_t igp_lane_info,
+                         uint16_t connector_object_id);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -193,6 +194,23 @@ const int supported_devices_connector_convert[] = {
        DRM_MODE_CONNECTOR_DisplayPort
 };
 
+const uint16_t supported_devices_connector_object_id_convert[] = {
+       CONNECTOR_OBJECT_ID_NONE,
+       CONNECTOR_OBJECT_ID_VGA,
+       CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
+       CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
+       CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
+       CONNECTOR_OBJECT_ID_COMPOSITE,
+       CONNECTOR_OBJECT_ID_SVIDEO,
+       CONNECTOR_OBJECT_ID_LVDS,
+       CONNECTOR_OBJECT_ID_9PIN_DIN,
+       CONNECTOR_OBJECT_ID_9PIN_DIN,
+       CONNECTOR_OBJECT_ID_DISPLAYPORT,
+       CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
+       CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
+       CONNECTOR_OBJECT_ID_SVIDEO
+};
+
 const int object_connector_convert[] = {
        DRM_MODE_CONNECTOR_Unknown,
        DRM_MODE_CONNECTOR_DVII,
@@ -229,7 +247,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
        ATOM_OBJECT_HEADER *obj_header;
        int i, j, path_size, device_support;
        int connector_type;
-       uint16_t igp_lane_info, conn_id;
+       uint16_t igp_lane_info, conn_id, connector_object_id;
        bool linkb;
        struct radeon_i2c_bus_rec ddc_bus;
 
@@ -277,7 +295,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                ATOM_DEVICE_CV_SUPPORT)
                                continue;
 
-                       if ((rdev->family == CHIP_RS780) &&
+                       /* IGP chips */
+                       if ((rdev->flags & RADEON_IS_IGP) &&
                            (con_obj_id ==
                             CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
                                uint16_t igp_offset = 0;
@@ -311,6 +330,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                connector_type =
                                                    object_connector_convert
                                                    [ct];
+                                               connector_object_id = ct;
                                                igp_lane_info =
                                                    slot_config & 0xffff;
                                        } else
@@ -321,6 +341,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                igp_lane_info = 0;
                                connector_type =
                                    object_connector_convert[con_obj_id];
+                               connector_object_id = con_obj_id;
                        }
 
                        if (connector_type == DRM_MODE_CONNECTOR_Unknown)
@@ -425,7 +446,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                  le16_to_cpu(path->
                                                              usDeviceTag),
                                                  connector_type, &ddc_bus,
-                                                 linkb, igp_lane_info);
+                                                 linkb, igp_lane_info,
+                                                 connector_object_id);
 
                }
        }
@@ -435,6 +457,45 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
        return true;
 }
 
+static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
+                                                int connector_type,
+                                                uint16_t devices)
+{
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (rdev->flags & RADEON_IS_IGP) {
+               return supported_devices_connector_object_id_convert
+                       [connector_type];
+       } else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
+                   (connector_type == DRM_MODE_CONNECTOR_DVID)) &&
+                  (devices & ATOM_DEVICE_DFP2_SUPPORT))  {
+               struct radeon_mode_info *mode_info = &rdev->mode_info;
+               struct atom_context *ctx = mode_info->atom_context;
+               int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
+               uint16_t size, data_offset;
+               uint8_t frev, crev;
+               ATOM_XTMDS_INFO *xtmds;
+
+               atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
+               xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
+
+               if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
+                       if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+                       else
+                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+               } else {
+                       if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+                       else
+                               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+               }
+       } else {
+               return supported_devices_connector_object_id_convert
+                       [connector_type];
+       }
+}
+
 struct bios_connector {
        bool valid;
        uint16_t line_mux;
@@ -593,14 +654,20 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 
        /* add the connectors */
        for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
-               if (bios_connectors[i].valid)
+               if (bios_connectors[i].valid) {
+                       uint16_t connector_object_id =
+                               atombios_get_connector_object_id(dev,
+                                                     bios_connectors[i].connector_type,
+                                                     bios_connectors[i].devices);
                        radeon_add_atom_connector(dev,
                                                  bios_connectors[i].line_mux,
                                                  bios_connectors[i].devices,
                                                  bios_connectors[i].
                                                  connector_type,
                                                  &bios_connectors[i].ddc_bus,
-                                                 false, 0);
+                                                 false, 0,
+                                                 connector_object_id);
+               }
        }
 
        radeon_link_encoder_connector(dev);
@@ -641,8 +708,12 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                    le16_to_cpu(firmware_info->info.usReferenceClock);
                p1pll->reference_div = 0;
 
-               p1pll->pll_out_min =
-                   le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
+               if (crev < 2)
+                       p1pll->pll_out_min =
+                               le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
+               else
+                       p1pll->pll_out_min =
+                               le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
                p1pll->pll_out_max =
                    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
 
@@ -651,6 +722,16 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                                p1pll->pll_out_min = 64800;
                        else
                                p1pll->pll_out_min = 20000;
+               } else if (p1pll->pll_out_min > 64800) {
+                       /* Limiting the pll output range is a good thing generally as
+                        * it limits the number of possible pll combinations for a given
+                        * frequency presumably to the ones that work best on each card.
+                        * However, certain duallink DVI monitors seem to like
+                        * pll combinations that would be limited by this at least on
+                        * pre-DCE 3.0 r6xx hardware.  This might need to be adjusted per
+                        * family.
+                        */
+                       p1pll->pll_out_min = 64800;
                }
 
                p1pll->pll_in_min =
@@ -767,6 +848,46 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
        return false;
 }
 
+static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
+                                                         radeon_encoder
+                                                         *encoder,
+                                                         int id)
+{
+       struct drm_device *dev = encoder->base.dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_mode_info *mode_info = &rdev->mode_info;
+       int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
+       uint16_t data_offset;
+       struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
+       uint8_t frev, crev;
+       struct radeon_atom_ss *ss = NULL;
+
+       if (id > ATOM_MAX_SS_ENTRY)
+               return NULL;
+
+       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
+                              &crev, &data_offset);
+
+       ss_info =
+           (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
+
+       if (ss_info) {
+               ss =
+                   kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
+
+               if (!ss)
+                       return NULL;
+
+               ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage);
+               ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType;
+               ss->step = ss_info->asSS_Info[id].ucSS_Step;
+               ss->delay = ss_info->asSS_Info[id].ucSS_Delay;
+               ss->range = ss_info->asSS_Info[id].ucSS_Range;
+               ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div;
+       }
+       return ss;
+}
+
 union lvds_info {
        struct _ATOM_LVDS_INFO info;
        struct _ATOM_LVDS_INFO_V12 info_12;
@@ -798,27 +919,31 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                if (!lvds)
                        return NULL;
 
-               lvds->native_mode.dotclock =
+               lvds->native_mode.clock =
                    le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
-               lvds->native_mode.panel_xres =
+               lvds->native_mode.hdisplay =
                    le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
-               lvds->native_mode.panel_yres =
+               lvds->native_mode.vdisplay =
                    le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
-               lvds->native_mode.hblank =
-                   le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
-               lvds->native_mode.hoverplus =
-                   le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
-               lvds->native_mode.hsync_width =
-                   le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
-               lvds->native_mode.vblank =
-                   le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
-               lvds->native_mode.voverplus =
-                   le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
-               lvds->native_mode.vsync_width =
-                   le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
+               lvds->native_mode.htotal = lvds->native_mode.hdisplay +
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
+               lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
+               lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
+               lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
+               lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
+               lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
                lvds->panel_pwr_delay =
                    le16_to_cpu(lvds_info->info.usOffDelayInMs);
                lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
+               /* set crtc values */
+               drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
+
+               lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
 
                encoder->native_mode = lvds->native_mode;
        }
@@ -857,8 +982,7 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
 }
 
 bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
-                               SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
-                               int32_t *pixel_clock)
+                               struct drm_display_mode *mode)
 {
        struct radeon_mode_info *mode_info = &rdev->mode_info;
        ATOM_ANALOG_TV_INFO *tv_info;
@@ -866,7 +990,7 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
        ATOM_DTD_FORMAT *dtd_timings;
        int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
        u8 frev, crev;
-       uint16_t data_offset;
+       u16 data_offset, misc;
 
        atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
 
@@ -876,28 +1000,37 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                if (index > MAX_SUPPORTED_TV_TIMING)
                        return false;
 
-               crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
-               crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
-               crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
-               crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
-
-               crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
-               crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
-               crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
-               crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
-
-               crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
-
-               crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
-               crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
-               crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
-               crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
-               *pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
+               mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
+               mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
+               mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
+               mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
+                       le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
+
+               mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
+               mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
+               mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
+               mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
+                       le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
+
+               mode->flags = 0;
+               misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
+               if (misc & ATOM_VSYNC_POLARITY)
+                       mode->flags |= DRM_MODE_FLAG_NVSYNC;
+               if (misc & ATOM_HSYNC_POLARITY)
+                       mode->flags |= DRM_MODE_FLAG_NHSYNC;
+               if (misc & ATOM_COMPOSITESYNC)
+                       mode->flags |= DRM_MODE_FLAG_CSYNC;
+               if (misc & ATOM_INTERLACE)
+                       mode->flags |= DRM_MODE_FLAG_INTERLACE;
+               if (misc & ATOM_DOUBLE_CLOCK_MODE)
+                       mode->flags |= DRM_MODE_FLAG_DBLSCAN;
+
+               mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
 
                if (index == 1) {
                        /* PAL timings appear to have wrong values for totals */
-                       crtc_timing->usH_Total -= 1;
-                       crtc_timing->usV_Total -= 1;
+                       mode->crtc_htotal -= 1;
+                       mode->crtc_vtotal -= 1;
                }
                break;
        case 2:
@@ -906,17 +1039,36 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                        return false;
 
                dtd_timings = &tv_info_v1_2->aModeTimings[index];
-               crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
-               crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive);
-               crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
-               crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth);
-               crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
-               crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive);
-               crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
-               crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth);
-
-               crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
-               *pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
+               mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
+                       le16_to_cpu(dtd_timings->usHBlanking_Time);
+               mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
+               mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
+                       le16_to_cpu(dtd_timings->usHSyncOffset);
+               mode->crtc_hsync_end = mode->crtc_hsync_start +
+                       le16_to_cpu(dtd_timings->usHSyncWidth);
+
+               mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
+                       le16_to_cpu(dtd_timings->usVBlanking_Time);
+               mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
+               mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
+                       le16_to_cpu(dtd_timings->usVSyncOffset);
+               mode->crtc_vsync_end = mode->crtc_vsync_start +
+                       le16_to_cpu(dtd_timings->usVSyncWidth);
+
+               mode->flags = 0;
+               misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
+               if (misc & ATOM_VSYNC_POLARITY)
+                       mode->flags |= DRM_MODE_FLAG_NVSYNC;
+               if (misc & ATOM_HSYNC_POLARITY)
+                       mode->flags |= DRM_MODE_FLAG_NHSYNC;
+               if (misc & ATOM_COMPOSITESYNC)
+                       mode->flags |= DRM_MODE_FLAG_CSYNC;
+               if (misc & ATOM_INTERLACE)
+                       mode->flags |= DRM_MODE_FLAG_INTERLACE;
+               if (misc & ATOM_DOUBLE_CLOCK_MODE)
+                       mode->flags |= DRM_MODE_FLAG_DBLSCAN;
+
+               mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
                break;
        }
        return true;
@@ -981,6 +1133,24 @@ void radeon_atom_static_pwrmgt_setup(struct radeon_device *rdev, int enable)
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
+{
+       GET_ENGINE_CLOCK_PS_ALLOCATION args;
+       int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+       return args.ulReturnEngineClock;
+}
+
+uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
+{
+       GET_MEMORY_CLOCK_PS_ALLOCATION args;
+       int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+       return args.ulReturnMemoryClock;
+}
+
 void radeon_atom_set_engine_clock(struct radeon_device *rdev,
                                  uint32_t eng_clock)
 {
index 2e938f7..10bd50a 100644 (file)
@@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
                if (r) {
                        goto out_cleanup;
                }
-               r = radeon_copy_dma(rdev, saddr, daddr, size / 4096, fence);
+               r = radeon_copy_dma(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence);
                if (r) {
                        goto out_cleanup;
                }
@@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
                if (r) {
                        goto out_cleanup;
                }
-               r = radeon_copy_blit(rdev, saddr, daddr, size / 4096, fence);
+               r = radeon_copy_blit(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence);
                if (r) {
                        goto out_cleanup;
                }
index 34a9b91..9069217 100644 (file)
@@ -50,19 +50,16 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
        vram_base = drm_get_resource_start(rdev->ddev, 0);
        bios = ioremap(vram_base, size);
        if (!bios) {
-               DRM_ERROR("Unable to mmap vram\n");
                return false;
        }
 
        if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
                iounmap(bios);
-               DRM_ERROR("bad rom signature\n");
                return false;
        }
        rdev->bios = kmalloc(size, GFP_KERNEL);
        if (rdev->bios == NULL) {
                iounmap(bios);
-               DRM_ERROR("kmalloc failed\n");
                return false;
        }
        memcpy(rdev->bios, bios, size);
index f5c32a7..a813541 100644 (file)
@@ -32,7 +32,7 @@
 #include "atom.h"
 
 /* 10 khz */
-static uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
+uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
 {
        struct radeon_pll *spll = &rdev->clock.spll;
        uint32_t fb_div, ref_div, post_div, sclk;
index 748265a..5253cbf 100644 (file)
@@ -49,7 +49,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
                            uint32_t connector_id,
                            uint32_t supported_device,
                            int connector_type,
-                           struct radeon_i2c_bus_rec *i2c_bus);
+                           struct radeon_i2c_bus_rec *i2c_bus,
+                           uint16_t connector_object_id);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -808,25 +809,25 @@ static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
        lvds->panel_blon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY2_SHIFT) & 0xf;
 
        if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE)
-               lvds->native_mode.panel_yres =
+               lvds->native_mode.vdisplay =
                    ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >>
                     RADEON_VERT_PANEL_SHIFT) + 1;
        else
-               lvds->native_mode.panel_yres =
+               lvds->native_mode.vdisplay =
                    (RREG32(RADEON_CRTC_V_TOTAL_DISP) >> 16) + 1;
 
        if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE)
-               lvds->native_mode.panel_xres =
+               lvds->native_mode.hdisplay =
                    (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >>
                      RADEON_HORZ_PANEL_SHIFT) + 1) * 8;
        else
-               lvds->native_mode.panel_xres =
+               lvds->native_mode.hdisplay =
                    ((RREG32(RADEON_CRTC_H_TOTAL_DISP) >> 16) + 1) * 8;
 
-       if ((lvds->native_mode.panel_xres < 640) ||
-           (lvds->native_mode.panel_yres < 480)) {
-               lvds->native_mode.panel_xres = 640;
-               lvds->native_mode.panel_yres = 480;
+       if ((lvds->native_mode.hdisplay < 640) ||
+           (lvds->native_mode.vdisplay < 480)) {
+               lvds->native_mode.hdisplay = 640;
+               lvds->native_mode.vdisplay = 480;
        }
 
        ppll_div_sel = RREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3;
@@ -846,8 +847,8 @@ static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
        lvds->panel_vcc_delay = 200;
 
        DRM_INFO("Panel info derived from registers\n");
-       DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.panel_xres,
-                lvds->native_mode.panel_yres);
+       DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.hdisplay,
+                lvds->native_mode.vdisplay);
 
        return lvds;
 }
@@ -882,11 +883,11 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
 
                DRM_INFO("Panel ID String: %s\n", stmp);
 
-               lvds->native_mode.panel_xres = RBIOS16(lcd_info + 0x19);
-               lvds->native_mode.panel_yres = RBIOS16(lcd_info + 0x1b);
+               lvds->native_mode.hdisplay = RBIOS16(lcd_info + 0x19);
+               lvds->native_mode.vdisplay = RBIOS16(lcd_info + 0x1b);
 
-               DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.panel_xres,
-                        lvds->native_mode.panel_yres);
+               DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.hdisplay,
+                        lvds->native_mode.vdisplay);
 
                lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c);
                if (lvds->panel_vcc_delay > 2000 || lvds->panel_vcc_delay < 0)
@@ -944,27 +945,25 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
                        if (tmp == 0)
                                break;
 
-                       if ((RBIOS16(tmp) == lvds->native_mode.panel_xres) &&
+                       if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) &&
                            (RBIOS16(tmp + 2) ==
-                            lvds->native_mode.panel_yres)) {
-                               lvds->native_mode.hblank =
-                                   (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8;
-                               lvds->native_mode.hoverplus =
-                                   (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) -
-                                    1) * 8;
-                               lvds->native_mode.hsync_width =
-                                   RBIOS8(tmp + 23) * 8;
-
-                               lvds->native_mode.vblank = (RBIOS16(tmp + 24) -
-                                                           RBIOS16(tmp + 26));
-                               lvds->native_mode.voverplus =
-                                   ((RBIOS16(tmp + 28) & 0x7ff) -
-                                    RBIOS16(tmp + 26));
-                               lvds->native_mode.vsync_width =
-                                   ((RBIOS16(tmp + 28) & 0xf800) >> 11);
-                               lvds->native_mode.dotclock =
-                                   RBIOS16(tmp + 9) * 10;
+                            lvds->native_mode.vdisplay)) {
+                               lvds->native_mode.htotal = RBIOS16(tmp + 17) * 8;
+                               lvds->native_mode.hsync_start = RBIOS16(tmp + 21) * 8;
+                               lvds->native_mode.hsync_end = (RBIOS8(tmp + 23) +
+                                                              RBIOS16(tmp + 21)) * 8;
+
+                               lvds->native_mode.vtotal = RBIOS16(tmp + 24);
+                               lvds->native_mode.vsync_start = RBIOS16(tmp + 28) & 0x7ff;
+                               lvds->native_mode.vsync_end =
+                                       ((RBIOS16(tmp + 28) & 0xf800) >> 11) +
+                                       (RBIOS16(tmp + 28) & 0x7ff);
+
+                               lvds->native_mode.clock = RBIOS16(tmp + 9) * 10;
                                lvds->native_mode.flags = 0;
+                               /* set crtc values */
+                               drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
+
                        }
                }
        } else {
@@ -1178,7 +1177,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        radeon_add_legacy_connector(dev, 0,
                                                    ATOM_DEVICE_CRT1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_VGA,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_VGA);
                } else if (rdev->flags & RADEON_IS_MOBILITY) {
                        /* LVDS */
                        ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
@@ -1190,7 +1190,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        radeon_add_legacy_connector(dev, 0,
                                                    ATOM_DEVICE_LCD1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_LVDS,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_LVDS);
 
                        /* VGA - primary dac */
                        ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
@@ -1202,7 +1203,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        radeon_add_legacy_connector(dev, 1,
                                                    ATOM_DEVICE_CRT1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_VGA,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_VGA);
                } else {
                        /* DVI-I - tv dac, int tmds */
                        ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
@@ -1220,7 +1222,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                    ATOM_DEVICE_DFP1_SUPPORT |
                                                    ATOM_DEVICE_CRT2_SUPPORT,
                                                    DRM_MODE_CONNECTOR_DVII,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 
                        /* VGA - primary dac */
                        ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
@@ -1232,7 +1235,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        radeon_add_legacy_connector(dev, 1,
                                                    ATOM_DEVICE_CRT1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_VGA,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_VGA);
                }
 
                if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
@@ -1245,7 +1249,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                        radeon_add_legacy_connector(dev, 2,
                                                    ATOM_DEVICE_TV1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_SVIDEO,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_SVIDEO);
                }
                break;
        case CT_IBOOK:
@@ -1259,7 +1264,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
                radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_LVDS);
                /* VGA - TV DAC */
                ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
                radeon_add_legacy_encoder(dev,
@@ -1268,7 +1274,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
                radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
-                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1277,7 +1284,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_POWERBOOK_EXTERNAL:
                DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
@@ -1290,7 +1298,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
                radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_LVDS);
                /* DVI-I - primary dac, ext tmds */
                ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
                radeon_add_legacy_encoder(dev,
@@ -1303,10 +1312,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                ATOM_DEVICE_CRT1_SUPPORT,
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
+               /* XXX some are SL */
                radeon_add_legacy_connector(dev, 1,
                                            ATOM_DEVICE_DFP2_SUPPORT |
                                            ATOM_DEVICE_CRT1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1315,7 +1326,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_POWERBOOK_INTERNAL:
                DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
@@ -1328,7 +1340,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
                radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_LVDS);
                /* DVI-I - primary dac, int tmds */
                ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
                radeon_add_legacy_encoder(dev,
@@ -1344,7 +1357,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                radeon_add_legacy_connector(dev, 1,
                                            ATOM_DEVICE_DFP1_SUPPORT |
                                            ATOM_DEVICE_CRT1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1353,7 +1367,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_POWERBOOK_VGA:
                DRM_INFO("Connector Table: %d (powerbook vga)\n",
@@ -1366,7 +1381,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                0),
                                          ATOM_DEVICE_LCD1_SUPPORT);
                radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_LVDS);
                /* VGA - primary dac */
                ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
                radeon_add_legacy_encoder(dev,
@@ -1375,7 +1391,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
                radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1384,7 +1401,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_MINI_EXTERNAL:
                DRM_INFO("Connector Table: %d (mini external tmds)\n",
@@ -1401,10 +1419,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                ATOM_DEVICE_CRT2_SUPPORT,
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
+               /* XXX are any DL? */
                radeon_add_legacy_connector(dev, 0,
                                            ATOM_DEVICE_DFP2_SUPPORT |
                                            ATOM_DEVICE_CRT2_SUPPORT,
-                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1413,7 +1433,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_MINI_INTERNAL:
                DRM_INFO("Connector Table: %d (mini internal tmds)\n",
@@ -1433,7 +1454,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                radeon_add_legacy_connector(dev, 0,
                                            ATOM_DEVICE_DFP1_SUPPORT |
                                            ATOM_DEVICE_CRT2_SUPPORT,
-                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1442,7 +1464,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_IMAC_G5_ISIGHT:
                DRM_INFO("Connector Table: %d (imac g5 isight)\n",
@@ -1455,7 +1478,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                0),
                                          ATOM_DEVICE_DFP1_SUPPORT);
                radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_DVID, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_DVID, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
                /* VGA - tv dac */
                ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
                radeon_add_legacy_encoder(dev,
@@ -1464,7 +1488,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
                radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
-                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1473,7 +1498,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        case CT_EMAC:
                DRM_INFO("Connector Table: %d (emac)\n",
@@ -1486,7 +1512,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                1),
                                          ATOM_DEVICE_CRT1_SUPPORT);
                radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
-                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA);
                /* VGA - tv dac */
                ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
                radeon_add_legacy_encoder(dev,
@@ -1495,7 +1522,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                                                2),
                                          ATOM_DEVICE_CRT2_SUPPORT);
                radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
-                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA);
                /* TV - TV DAC */
                radeon_add_legacy_encoder(dev,
                                          radeon_get_encoder_id(dev,
@@ -1504,7 +1532,8 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                          ATOM_DEVICE_TV1_SUPPORT);
                radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
                                            DRM_MODE_CONNECTOR_SVIDEO,
-                                           &ddc_i2c);
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO);
                break;
        default:
                DRM_INFO("Connector table: %d (invalid)\n",
@@ -1581,11 +1610,63 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
        return true;
 }
 
+static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev)
+{
+       /* Acer 5102 has non-existent TV port */
+       if (dev->pdev->device == 0x5975 &&
+           dev->pdev->subsystem_vendor == 0x1025 &&
+           dev->pdev->subsystem_device == 0x009f)
+               return false;
+
+       /* HP dc5750 has non-existent TV port */
+       if (dev->pdev->device == 0x5974 &&
+           dev->pdev->subsystem_vendor == 0x103c &&
+           dev->pdev->subsystem_device == 0x280a)
+               return false;
+
+       return true;
+}
+
+static uint16_t combios_check_dl_dvi(struct drm_device *dev, int is_dvi_d)
+{
+       struct radeon_device *rdev = dev->dev_private;
+       uint32_t ext_tmds_info;
+
+       if (rdev->flags & RADEON_IS_IGP) {
+               if (is_dvi_d)
+                       return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+               else
+                       return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+       }
+       ext_tmds_info = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
+       if (ext_tmds_info) {
+               uint8_t rev = RBIOS8(ext_tmds_info);
+               uint8_t flags = RBIOS8(ext_tmds_info + 4 + 5);
+               if (rev >= 3) {
+                       if (is_dvi_d)
+                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+                       else
+                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+               } else {
+                       if (flags & 1) {
+                               if (is_dvi_d)
+                                       return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+                               else
+                                       return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+                       }
+               }
+       }
+       if (is_dvi_d)
+               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+       else
+               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+}
+
 bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
        uint32_t conn_info, entry, devices;
-       uint16_t tmp;
+       uint16_t tmp, connector_object_id;
        enum radeon_combios_ddc ddc_type;
        enum radeon_combios_connector connector;
        int i = 0;
@@ -1628,8 +1709,9 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                break;
                        }
 
-                       radeon_apply_legacy_quirks(dev, i, &connector,
-                                                  &ddc_i2c);
+                       if (!radeon_apply_legacy_quirks(dev, i, &connector,
+                                                      &ddc_i2c))
+                               continue;
 
                        switch (connector) {
                        case CONNECTOR_PROPRIETARY_LEGACY:
@@ -1644,7 +1726,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                radeon_add_legacy_connector(dev, i, devices,
                                                            legacy_connector_convert
                                                            [connector],
-                                                           &ddc_i2c);
+                                                           &ddc_i2c,
+                                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
                                break;
                        case CONNECTOR_CRT_LEGACY:
                                if (tmp & 0x1) {
@@ -1669,7 +1752,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                            devices,
                                                            legacy_connector_convert
                                                            [connector],
-                                                           &ddc_i2c);
+                                                           &ddc_i2c,
+                                                           CONNECTOR_OBJECT_ID_VGA);
                                break;
                        case CONNECTOR_DVI_I_LEGACY:
                                devices = 0;
@@ -1698,6 +1782,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                                   ATOM_DEVICE_DFP2_SUPPORT,
                                                                   0),
                                                                  ATOM_DEVICE_DFP2_SUPPORT);
+                                       connector_object_id = combios_check_dl_dvi(dev, 0);
                                } else {
                                        devices |= ATOM_DEVICE_DFP1_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
@@ -1706,19 +1791,24 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                                   ATOM_DEVICE_DFP1_SUPPORT,
                                                                   0),
                                                                  ATOM_DEVICE_DFP1_SUPPORT);
+                                       connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
                                }
                                radeon_add_legacy_connector(dev,
                                                            i,
                                                            devices,
                                                            legacy_connector_convert
                                                            [connector],
-                                                           &ddc_i2c);
+                                                           &ddc_i2c,
+                                                           connector_object_id);
                                break;
                        case CONNECTOR_DVI_D_LEGACY:
-                               if ((tmp >> 4) & 0x1)
+                               if ((tmp >> 4) & 0x1) {
                                        devices = ATOM_DEVICE_DFP2_SUPPORT;
-                               else
+                                       connector_object_id = combios_check_dl_dvi(dev, 1);
+                               } else {
                                        devices = ATOM_DEVICE_DFP1_SUPPORT;
+                                       connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+                               }
                                radeon_add_legacy_encoder(dev,
                                                          radeon_get_encoder_id
                                                          (dev, devices, 0),
@@ -1726,7 +1816,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                radeon_add_legacy_connector(dev, i, devices,
                                                            legacy_connector_convert
                                                            [connector],
-                                                           &ddc_i2c);
+                                                           &ddc_i2c,
+                                                           connector_object_id);
                                break;
                        case CONNECTOR_CTV_LEGACY:
                        case CONNECTOR_STV_LEGACY:
@@ -1740,7 +1831,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                            ATOM_DEVICE_TV1_SUPPORT,
                                                            legacy_connector_convert
                                                            [connector],
-                                                           &ddc_i2c);
+                                                           &ddc_i2c,
+                                                           CONNECTOR_OBJECT_ID_SVIDEO);
                                break;
                        default:
                                DRM_ERROR("Unknown connector type: %d\n",
@@ -1772,10 +1864,29 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                    ATOM_DEVICE_CRT1_SUPPORT |
                                                    ATOM_DEVICE_DFP1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_DVII,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
                } else {
-                       DRM_DEBUG("No connector info found\n");
-                       return false;
+                       uint16_t crt_info =
+                               combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
+                       DRM_DEBUG("Found CRT table, assuming VGA connector\n");
+                       if (crt_info) {
+                               radeon_add_legacy_encoder(dev,
+                                                         radeon_get_encoder_id(dev,
+                                                                               ATOM_DEVICE_CRT1_SUPPORT,
+                                                                               1),
+                                                         ATOM_DEVICE_CRT1_SUPPORT);
+                               ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+                               radeon_add_legacy_connector(dev,
+                                                           0,
+                                                           ATOM_DEVICE_CRT1_SUPPORT,
+                                                           DRM_MODE_CONNECTOR_VGA,
+                                                           &ddc_i2c,
+                                                           CONNECTOR_OBJECT_ID_VGA);
+                       } else {
+                               DRM_DEBUG("No connector info found\n");
+                               return false;
+                       }
                }
        }
 
@@ -1870,7 +1981,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                    5,
                                                    ATOM_DEVICE_LCD1_SUPPORT,
                                                    DRM_MODE_CONNECTOR_LVDS,
-                                                   &ddc_i2c);
+                                                   &ddc_i2c,
+                                                   CONNECTOR_OBJECT_ID_LVDS);
                }
        }
 
@@ -1880,16 +1992,19 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                    combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
                if (tv_info) {
                        if (RBIOS8(tv_info + 6) == 'T') {
-                               radeon_add_legacy_encoder(dev,
-                                                         radeon_get_encoder_id
-                                                         (dev,
-                                                          ATOM_DEVICE_TV1_SUPPORT,
-                                                          2),
-                                                         ATOM_DEVICE_TV1_SUPPORT);
-                               radeon_add_legacy_connector(dev, 6,
-                                                           ATOM_DEVICE_TV1_SUPPORT,
-                                                           DRM_MODE_CONNECTOR_SVIDEO,
-                                                           &ddc_i2c);
+                               if (radeon_apply_legacy_tv_quirks(dev)) {
+                                       radeon_add_legacy_encoder(dev,
+                                                                 radeon_get_encoder_id
+                                                                 (dev,
+                                                                  ATOM_DEVICE_TV1_SUPPORT,
+                                                                  2),
+                                                                 ATOM_DEVICE_TV1_SUPPORT);
+                                       radeon_add_legacy_connector(dev, 6,
+                                                                   ATOM_DEVICE_TV1_SUPPORT,
+                                                                   DRM_MODE_CONNECTOR_SVIDEO,
+                                                                   &ddc_i2c,
+                                                                   CONNECTOR_OBJECT_ID_SVIDEO);
+                               }
                        }
                }
        }
index e376be4..fce4c40 100644 (file)
@@ -178,25 +178,12 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode
        struct drm_device *dev = encoder->dev;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_display_mode *mode = NULL;
-       struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
-
-       if (native_mode->panel_xres != 0 &&
-           native_mode->panel_yres != 0 &&
-           native_mode->dotclock != 0) {
-               mode = drm_mode_create(dev);
-
-               mode->hdisplay = native_mode->panel_xres;
-               mode->vdisplay = native_mode->panel_yres;
-
-               mode->htotal = mode->hdisplay + native_mode->hblank;
-               mode->hsync_start = mode->hdisplay + native_mode->hoverplus;
-               mode->hsync_end = mode->hsync_start + native_mode->hsync_width;
-               mode->vtotal = mode->vdisplay + native_mode->vblank;
-               mode->vsync_start = mode->vdisplay + native_mode->voverplus;
-               mode->vsync_end = mode->vsync_start + native_mode->vsync_width;
-               mode->clock = native_mode->dotclock;
-               mode->flags = 0;
+       struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
 
+       if (native_mode->hdisplay != 0 &&
+           native_mode->vdisplay != 0 &&
+           native_mode->clock != 0) {
+               mode = drm_mode_duplicate(dev, native_mode);
                mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
                drm_mode_set_name(mode);
 
@@ -210,7 +197,7 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn
        struct drm_device *dev = encoder->dev;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_display_mode *mode = NULL;
-       struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
+       struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
        int i;
        struct mode_size {
                int w;
@@ -236,11 +223,16 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn
        };
 
        for (i = 0; i < 17; i++) {
+               if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
+                       if (common_modes[i].w > 1024 ||
+                           common_modes[i].h > 768)
+                               continue;
+               }
                if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                       if (common_modes[i].w > native_mode->panel_xres ||
-                           common_modes[i].h > native_mode->panel_yres ||
-                           (common_modes[i].w == native_mode->panel_xres &&
-                            common_modes[i].h == native_mode->panel_yres))
+                       if (common_modes[i].w > native_mode->hdisplay ||
+                           common_modes[i].h > native_mode->vdisplay ||
+                           (common_modes[i].w == native_mode->hdisplay &&
+                            common_modes[i].h == native_mode->vdisplay))
                                continue;
                }
                if (common_modes[i].w < 320 || common_modes[i].h < 200)
@@ -344,28 +336,23 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
                                          struct drm_connector *connector)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
+       struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
 
        /* Try to get native mode details from EDID if necessary */
-       if (!native_mode->dotclock) {
+       if (!native_mode->clock) {
                struct drm_display_mode *t, *mode;
 
                list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
-                       if (mode->hdisplay == native_mode->panel_xres &&
-                           mode->vdisplay == native_mode->panel_yres) {
-                               native_mode->hblank = mode->htotal - mode->hdisplay;
-                               native_mode->hoverplus = mode->hsync_start - mode->hdisplay;
-                               native_mode->hsync_width = mode->hsync_end - mode->hsync_start;
-                               native_mode->vblank = mode->vtotal - mode->vdisplay;
-                               native_mode->voverplus = mode->vsync_start - mode->vdisplay;
-                               native_mode->vsync_width = mode->vsync_end - mode->vsync_start;
-                               native_mode->dotclock = mode->clock;
+                       if (mode->hdisplay == native_mode->hdisplay &&
+                           mode->vdisplay == native_mode->vdisplay) {
+                               *native_mode = *mode;
+                               drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V);
                                DRM_INFO("Determined LVDS native mode details from EDID\n");
                                break;
                        }
                }
        }
-       if (!native_mode->dotclock) {
+       if (!native_mode->clock) {
                DRM_INFO("No LVDS native mode details, disabling RMX\n");
                radeon_encoder->rmx_type = RMX_OFF;
        }
@@ -410,13 +397,64 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
 static int radeon_lvds_mode_valid(struct drm_connector *connector,
                                  struct drm_display_mode *mode)
 {
+       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+
+       if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
+               return MODE_PANEL;
+
+       if (encoder) {
+               struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+               struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+
+               /* AVIVO hardware supports downscaling modes larger than the panel
+                * to the panel size, but I'm not sure this is desirable.
+                */
+               if ((mode->hdisplay > native_mode->hdisplay) ||
+                   (mode->vdisplay > native_mode->vdisplay))
+                       return MODE_PANEL;
+
+               /* if scaling is disabled, block non-native modes */
+               if (radeon_encoder->rmx_type == RMX_OFF) {
+                       if ((mode->hdisplay != native_mode->hdisplay) ||
+                           (mode->vdisplay != native_mode->vdisplay))
+                               return MODE_PANEL;
+               }
+       }
+
        return MODE_OK;
 }
 
 static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
 {
-       enum drm_connector_status ret = connector_status_connected;
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+       enum drm_connector_status ret = connector_status_disconnected;
+
+       if (encoder) {
+               struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+               struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+
+               /* check if panel is valid */
+               if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
+                       ret = connector_status_connected;
+
+       }
+
+       /* check for edid as well */
+       if (radeon_connector->edid)
+               ret = connector_status_connected;
+       else {
+               if (radeon_connector->ddc_bus) {
+                       radeon_i2c_do_lock(radeon_connector, 1);
+                       radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+                                                             &radeon_connector->ddc_bus->adapter);
+                       radeon_i2c_do_lock(radeon_connector, 0);
+                       if (radeon_connector->edid)
+                               ret = connector_status_connected;
+               }
+       }
        /* check acpi lid status ??? */
+
        radeon_connector_update_scratch_regs(connector, ret);
        return ret;
 }
@@ -427,6 +465,8 @@ static void radeon_connector_destroy(struct drm_connector *connector)
 
        if (radeon_connector->ddc_bus)
                radeon_i2c_destroy(radeon_connector->ddc_bus);
+       if (radeon_connector->edid)
+               kfree(radeon_connector->edid);
        kfree(radeon_connector->con_priv);
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
@@ -496,6 +536,8 @@ static int radeon_vga_get_modes(struct drm_connector *connector)
 static int radeon_vga_mode_valid(struct drm_connector *connector,
                                  struct drm_display_mode *mode)
 {
+       /* XXX check mode bandwidth */
+       /* XXX verify against max DAC output frequency */
        return MODE_OK;
 }
 
@@ -514,9 +556,32 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
        radeon_i2c_do_lock(radeon_connector, 1);
        dret = radeon_ddc_probe(radeon_connector);
        radeon_i2c_do_lock(radeon_connector, 0);
-       if (dret)
-               ret = connector_status_connected;
-       else {
+       if (dret) {
+               if (radeon_connector->edid) {
+                       kfree(radeon_connector->edid);
+                       radeon_connector->edid = NULL;
+               }
+               radeon_i2c_do_lock(radeon_connector, 1);
+               radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+               radeon_i2c_do_lock(radeon_connector, 0);
+
+               if (!radeon_connector->edid) {
+                       DRM_ERROR("DDC responded but not EDID found for %s\n",
+                                 drm_get_connector_name(connector));
+               } else {
+                       radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
+
+                       /* some oems have boards with separate digital and analog connectors
+                        * with a shared ddc line (often vga + hdmi)
+                        */
+                       if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
+                               kfree(radeon_connector->edid);
+                               radeon_connector->edid = NULL;
+                               ret = connector_status_disconnected;
+                       } else
+                               ret = connector_status_connected;
+               }
+       } else {
                if (radeon_connector->dac_load_detect) {
                        encoder_funcs = encoder->helper_private;
                        ret = encoder_funcs->detect(encoder, connector);
@@ -570,6 +635,8 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
 static int radeon_tv_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
+       if ((mode->hdisplay > 1024) || (mode->vdisplay > 768))
+               return MODE_CLOCK_RANGE;
        return MODE_OK;
 }
 
@@ -644,6 +711,10 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
        dret = radeon_ddc_probe(radeon_connector);
        radeon_i2c_do_lock(radeon_connector, 0);
        if (dret) {
+               if (radeon_connector->edid) {
+                       kfree(radeon_connector->edid);
+                       radeon_connector->edid = NULL;
+               }
                radeon_i2c_do_lock(radeon_connector, 1);
                radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
                radeon_i2c_do_lock(radeon_connector, 0);
@@ -654,10 +725,15 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 
-                       /* if this isn't a digital monitor
-                          then we need to make sure we don't have any
-                          TV conflicts */
-                       ret = connector_status_connected;
+                       /* some oems have boards with separate digital and analog connectors
+                        * with a shared ddc line (often vga + hdmi)
+                        */
+                       if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
+                               kfree(radeon_connector->edid);
+                               radeon_connector->edid = NULL;
+                               ret = connector_status_disconnected;
+                       } else
+                               ret = connector_status_connected;
                }
        }
 
@@ -753,9 +829,27 @@ static void radeon_dvi_force(struct drm_connector *connector)
                radeon_connector->use_digital = true;
 }
 
+static int radeon_dvi_mode_valid(struct drm_connector *connector,
+                                 struct drm_display_mode *mode)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+       /* XXX check mode bandwidth */
+
+       if (radeon_connector->use_digital && (mode->clock > 165000)) {
+               if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
+                   (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
+                   (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
+                       return MODE_OK;
+               else
+                       return MODE_CLOCK_HIGH;
+       }
+       return MODE_OK;
+}
+
 struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
        .get_modes = radeon_dvi_get_modes,
-       .mode_valid = radeon_vga_mode_valid,
+       .mode_valid = radeon_dvi_mode_valid,
        .best_encoder = radeon_dvi_encoder,
 };
 
@@ -775,13 +869,15 @@ radeon_add_atom_connector(struct drm_device *dev,
                          int connector_type,
                          struct radeon_i2c_bus_rec *i2c_bus,
                          bool linkb,
-                         uint32_t igp_lane_info)
+                         uint32_t igp_lane_info,
+                         uint16_t connector_object_id)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector;
        struct radeon_connector_atom_dig *radeon_dig_connector;
        uint32_t subpixel_order = SubPixelNone;
+       bool shared_ddc = false;
        int ret;
 
        /* fixme - tv/cv/din */
@@ -795,6 +891,13 @@ radeon_add_atom_connector(struct drm_device *dev,
                        radeon_connector->devices |= supported_device;
                        return;
                }
+               if (radeon_connector->ddc_bus && i2c_bus->valid) {
+                       if (memcmp(&radeon_connector->ddc_bus->rec, i2c_bus,
+                                   sizeof(struct radeon_i2c_bus_rec)) == 0) {
+                               radeon_connector->shared_ddc = true;
+                               shared_ddc = true;
+                       }
+               }
        }
 
        radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
@@ -805,6 +908,8 @@ radeon_add_atom_connector(struct drm_device *dev,
 
        radeon_connector->connector_id = connector_id;
        radeon_connector->devices = supported_device;
+       radeon_connector->shared_ddc = shared_ddc;
+       radeon_connector->connector_object_id = connector_object_id;
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_VGA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -956,7 +1061,8 @@ radeon_add_legacy_connector(struct drm_device *dev,
                            uint32_t connector_id,
                            uint32_t supported_device,
                            int connector_type,
-                           struct radeon_i2c_bus_rec *i2c_bus)
+                           struct radeon_i2c_bus_rec *i2c_bus,
+                           uint16_t connector_object_id)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_connector *connector;
@@ -985,6 +1091,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 
        radeon_connector->connector_id = connector_id;
        radeon_connector->devices = supported_device;
+       radeon_connector->connector_object_id = connector_object_id;
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_VGA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
index 4f7afc7..0b2f9c2 100644 (file)
@@ -1941,8 +1941,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev)
        for (t = 0; t < dev_priv->usec_timeout; t++) {
                u32 done_age = GET_SCRATCH(dev_priv, 1);
                DRM_DEBUG("done_age = %d\n", done_age);
-               for (i = start; i < dma->buf_count; i++) {
-                       buf = dma->buflist[i];
+               for (i = 0; i < dma->buf_count; i++) {
+                       buf = dma->buflist[start];
                        buf_priv = buf->dev_private;
                        if (buf->file_priv == NULL || (buf->pending &&
                                                       buf_priv->age <=
@@ -1951,7 +1951,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev)
                                buf->pending = 0;
                                return buf;
                        }
-                       start = 0;
+                       if (++start >= dma->buf_count)
+                               start = 0;
                }
 
                if (t) {
@@ -1960,47 +1961,9 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev)
                }
        }
 
-       DRM_DEBUG("returning NULL!\n");
        return NULL;
 }
 
-#if 0
-struct drm_buf *radeon_freelist_get(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv;
-       struct drm_buf *buf;
-       int i, t;
-       int start;
-       u32 done_age;
-
-       done_age = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1));
-       if (++dev_priv->last_buf >= dma->buf_count)
-               dev_priv->last_buf = 0;
-
-       start = dev_priv->last_buf;
-       dev_priv->stats.freelist_loops++;
-
-       for (t = 0; t < 2; t++) {
-               for (i = start; i < dma->buf_count; i++) {
-                       buf = dma->buflist[i];
-                       buf_priv = buf->dev_private;
-                       if (buf->file_priv == 0 || (buf->pending &&
-                                                   buf_priv->age <=
-                                                   done_age)) {
-                               dev_priv->stats.requested_bufs++;
-                               buf->pending = 0;
-                               return buf;
-                       }
-               }
-               start = 0;
-       }
-
-       return NULL;
-}
-#endif
-
 void radeon_freelist_reset(struct drm_device * dev)
 {
        struct drm_device_dma *dma = dev->dma;
index b13c79e..28772a3 100644 (file)
@@ -109,9 +109,15 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_device *rdev = crtc->dev->dev_private;
 
-       if (ASIC_IS_AVIVO(rdev))
+       if (ASIC_IS_AVIVO(rdev)) {
+               if (rdev->family >= CHIP_RV770) {
+                       if (radeon_crtc->crtc_id)
+                               WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, 0);
+                       else
+                               WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0);
+               }
                WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
-       else {
+       else {
                radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
                /* offset is from DISP(2)_BASE_ADDRESS */
                WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
index df98814..e3f9edf 100644 (file)
@@ -444,20 +444,24 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
        return r;
 }
 
-static struct card_info atom_card_info = {
-       .dev = NULL,
-       .reg_read = cail_reg_read,
-       .reg_write = cail_reg_write,
-       .mc_read = cail_mc_read,
-       .mc_write = cail_mc_write,
-       .pll_read = cail_pll_read,
-       .pll_write = cail_pll_write,
-};
-
 int radeon_atombios_init(struct radeon_device *rdev)
 {
-       atom_card_info.dev = rdev->ddev;
-       rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios);
+       struct card_info *atom_card_info =
+           kzalloc(sizeof(struct card_info), GFP_KERNEL);
+
+       if (!atom_card_info)
+               return -ENOMEM;
+
+       rdev->mode_info.atom_card_info = atom_card_info;
+       atom_card_info->dev = rdev->ddev;
+       atom_card_info->reg_read = cail_reg_read;
+       atom_card_info->reg_write = cail_reg_write;
+       atom_card_info->mc_read = cail_mc_read;
+       atom_card_info->mc_write = cail_mc_write;
+       atom_card_info->pll_read = cail_pll_read;
+       atom_card_info->pll_write = cail_pll_write;
+
+       rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
        radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
        return 0;
 }
@@ -465,6 +469,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
 void radeon_atombios_fini(struct radeon_device *rdev)
 {
        kfree(rdev->mode_info.atom_context);
+       kfree(rdev->mode_info.atom_card_info);
 }
 
 int radeon_combios_init(struct radeon_device *rdev)
index 3655d91..c85df4a 100644 (file)
@@ -137,9 +137,6 @@ static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
        if (size != 256) {
                return;
        }
-       if (crtc->fb == NULL) {
-               return;
-       }
 
        /* userspace palettes are always correct as is */
        for (i = 0; i < 256; i++) {
@@ -147,7 +144,6 @@ static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
                radeon_crtc->lut_g[i] = green[i] >> 6;
                radeon_crtc->lut_b[i] = blue[i] >> 6;
        }
-
        radeon_crtc_load_lut(crtc);
 }
 
@@ -338,27 +334,19 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 
 int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
 {
-       struct edid *edid;
        int ret = 0;
 
        if (!radeon_connector->ddc_bus)
                return -1;
        if (!radeon_connector->edid) {
                radeon_i2c_do_lock(radeon_connector, 1);
-               edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+               radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
                radeon_i2c_do_lock(radeon_connector, 0);
-       } else
-               edid = radeon_connector->edid;
+       }
 
-       if (edid) {
-               /* update digital bits here */
-               if (edid->input & DRM_EDID_INPUT_DIGITAL)
-                       radeon_connector->use_digital = 1;
-               else
-                       radeon_connector->use_digital = 0;
-               drm_mode_connector_update_edid_property(&radeon_connector->base, edid);
-               ret = drm_add_edid_modes(&radeon_connector->base, edid);
-               kfree(edid);
+       if (radeon_connector->edid) {
+               drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
+               ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
                return ret;
        }
        drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
@@ -765,7 +753,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
                        radeon_crtc->rmx_type = radeon_encoder->rmx_type;
                        memcpy(&radeon_crtc->native_mode,
                                &radeon_encoder->native_mode,
-                               sizeof(struct radeon_native_mode));
+                               sizeof(struct drm_display_mode));
                        first = false;
                } else {
                        if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
@@ -783,10 +771,10 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
        if (radeon_crtc->rmx_type != RMX_OFF) {
                fixed20_12 a, b;
                a.full = rfixed_const(crtc->mode.vdisplay);
-               b.full = rfixed_const(radeon_crtc->native_mode.panel_xres);
+               b.full = rfixed_const(radeon_crtc->native_mode.hdisplay);
                radeon_crtc->vsc.full = rfixed_div(a, b);
                a.full = rfixed_const(crtc->mode.hdisplay);
-               b.full = rfixed_const(radeon_crtc->native_mode.panel_yres);
+               b.full = rfixed_const(radeon_crtc->native_mode.vdisplay);
                radeon_crtc->hsc.full = rfixed_div(a, b);
        } else {
                radeon_crtc->vsc.full = rfixed_const(1);
index a65ab1a..d42bc51 100644 (file)
 
 extern int atom_debug;
 
+/* evil but including atombios.h is much worse */
+bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
+                               struct drm_display_mode *mode);
+
 uint32_t
 radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
 {
@@ -167,49 +171,17 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
-       struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
-
-       if (mode->hdisplay < native_mode->panel_xres ||
-           mode->vdisplay < native_mode->panel_yres) {
-               if (ASIC_IS_AVIVO(rdev)) {
-                       adjusted_mode->hdisplay = native_mode->panel_xres;
-                       adjusted_mode->vdisplay = native_mode->panel_yres;
-                       adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank;
-                       adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus;
-                       adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width;
-                       adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank;
-                       adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus;
-                       adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width;
-                       /* update crtc values */
-                       drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-                       /* adjust crtc values */
-                       adjusted_mode->crtc_hdisplay = native_mode->panel_xres;
-                       adjusted_mode->crtc_vdisplay = native_mode->panel_yres;
-                       adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank;
-                       adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus;
-                       adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width;
-                       adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank;
-                       adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus;
-                       adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width;
-               } else {
-                       adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank;
-                       adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus;
-                       adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width;
-                       adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank;
-                       adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus;
-                       adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width;
-                       /* update crtc values */
-                       drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-                       /* adjust crtc values */
-                       adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank;
-                       adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus;
-                       adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width;
-                       adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank;
-                       adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus;
-                       adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width;
+       struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+
+       if (mode->hdisplay < native_mode->hdisplay ||
+           mode->vdisplay < native_mode->vdisplay) {
+               int mode_id = adjusted_mode->base.id;
+               *adjusted_mode = *native_mode;
+               if (!ASIC_IS_AVIVO(rdev)) {
+                       adjusted_mode->hdisplay = mode->hdisplay;
+                       adjusted_mode->vdisplay = mode->vdisplay;
                }
-               adjusted_mode->flags = native_mode->flags;
-               adjusted_mode->clock = native_mode->dotclock;
+               adjusted_mode->base.id = mode_id;
        }
 }
 
@@ -219,7 +191,11 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
                                   struct drm_display_mode *adjusted_mode)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
 
+       /* 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)
@@ -230,6 +206,18 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
            && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
                adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
 
+       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+               struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
+               if (tv_dac) {
+                       if (tv_dac->tv_std == TV_STD_NTSC ||
+                           tv_dac->tv_std == TV_STD_NTSC_J ||
+                           tv_dac->tv_std == TV_STD_PAL_M)
+                               radeon_atom_get_tv_timings(rdev, 0, adjusted_mode);
+                       else
+                               radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
+               }
+       }
+
        return true;
 }
 
@@ -461,7 +449,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                case 1:
                        args.v1.ucMisc = 0;
                        args.v1.ucAction = action;
-                       if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+                       if (drm_detect_hdmi_monitor(radeon_connector->edid))
                                args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
                        args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
                        if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
@@ -486,7 +474,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
                                if (dig->coherent_mode)
                                        args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
                        }
-                       if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+                       if (drm_detect_hdmi_monitor(radeon_connector->edid))
                                args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
                        args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
                        args.v2.ucTruncate = 0;
@@ -544,7 +532,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        switch (connector->connector_type) {
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-               if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+               if (drm_detect_hdmi_monitor(radeon_connector->edid))
                        return ATOM_ENCODER_MODE_HDMI;
                else if (radeon_connector->use_digital)
                        return ATOM_ENCODER_MODE_DVI;
@@ -554,7 +542,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_DVID:
        case DRM_MODE_CONNECTOR_HDMIA:
        default:
-               if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+               if (drm_detect_hdmi_monitor(radeon_connector->edid))
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
@@ -566,7 +554,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                /*if (radeon_output->MonType == MT_DP)
                  return ATOM_ENCODER_MODE_DP;
                  else*/
-               if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+               if (drm_detect_hdmi_monitor(radeon_connector->edid))
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
@@ -734,14 +722,17 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
        atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
 
        args.v1.ucAction = action;
-
+       if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+               args.v1.usInitInfo = radeon_connector->connector_object_id;
+       } else {
+               if (radeon_encoder->pixel_clock > 165000)
+                       args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
+               else
+                       args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+       }
        if (ASIC_IS_DCE32(rdev)) {
-               if (radeon_encoder->pixel_clock > 165000) {
-                       args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 2) / 100);
-                       args.v2.acConfig.fDualLinkConnector = 1;
-               } else {
-                       args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 4) / 100);
-               }
+               if (radeon_encoder->pixel_clock > 165000)
+                       args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
                if (dig->dig_block)
                        args.v2.acConfig.ucEncoderSel = 1;
 
@@ -766,7 +757,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
                }
        } else {
                args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
-               args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock) / 10);
 
                switch (radeon_encoder->encoder_id) {
                case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
@@ -874,16 +864,9 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
        int index = 0;
        bool is_dig = false;
-       int devices;
 
        memset(&args, 0, sizeof(args));
 
-       /* on DPMS off we have no idea if active device is meaningful */
-       if (mode != DRM_MODE_DPMS_ON && !radeon_encoder->active_device)
-               devices = radeon_encoder->devices;
-       else
-               devices = radeon_encoder->active_device;
-
        DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
                  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
                  radeon_encoder->active_device);
@@ -914,18 +897,18 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DAC1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-               if (devices & (ATOM_DEVICE_TV_SUPPORT))
+               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
                        index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-               else if (devices & (ATOM_DEVICE_CV_SUPPORT))
+               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
                        index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
                else
                        index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DAC2:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               if (devices & (ATOM_DEVICE_TV_SUPPORT))
+               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
                        index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-               else if (devices & (ATOM_DEVICE_CV_SUPPORT))
+               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
                        index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
                else
                        index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
@@ -1104,8 +1087,11 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,
        }
 
        /* set scaler clears this on some chips */
-       if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
-               WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN);
+       if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
+               if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
+                       WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+                              AVIVO_D1MODE_INTERLEAVE_EN);
+       }
 }
 
 static void
@@ -1153,6 +1139,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 
                /* setup and enable the encoder and transmitter */
                atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
+               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT);
                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP);
                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
                break;
@@ -1268,8 +1255,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 {
        radeon_atom_output_lock(encoder, true);
        radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-
-       radeon_encoder_set_active_device(encoder);
 }
 
 static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
index a931af0..a68d756 100644 (file)
@@ -140,15 +140,15 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
                WARN(1, "trying to unbind memory to unitialized GART !\n");
                return;
        }
-       t = offset / 4096;
-       p = t / (PAGE_SIZE / 4096);
+       t = offset / RADEON_GPU_PAGE_SIZE;
+       p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
        for (i = 0; i < pages; i++, p++) {
                if (rdev->gart.pages[p]) {
                        pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
                                       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
                        rdev->gart.pages[p] = NULL;
                        rdev->gart.pages_addr[p] = 0;
-                       for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
+                       for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
                                radeon_gart_set_page(rdev, t, 0);
                        }
                }
@@ -169,8 +169,8 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
                DRM_ERROR("trying to bind memory to unitialized GART !\n");
                return -EINVAL;
        }
-       t = offset / 4096;
-       p = t / (PAGE_SIZE / 4096);
+       t = offset / RADEON_GPU_PAGE_SIZE;
+       p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 
        for (i = 0; i < pages; i++, p++) {
                /* we need to support large memory configurations */
@@ -185,9 +185,9 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
                }
                rdev->gart.pages[p] = pagelist[i];
                page_base = rdev->gart.pages_addr[p];
-               for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
+               for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
                        radeon_gart_set_page(rdev, t, page_base);
-                       page_base += 4096;
+                       page_base += RADEON_GPU_PAGE_SIZE;
                }
        }
        mb();
@@ -200,14 +200,14 @@ int radeon_gart_init(struct radeon_device *rdev)
        if (rdev->gart.pages) {
                return 0;
        }
-       /* We need PAGE_SIZE >= 4096 */
-       if (PAGE_SIZE < 4096) {
+       /* We need PAGE_SIZE >= RADEON_GPU_PAGE_SIZE */
+       if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) {
                DRM_ERROR("Page size is smaller than GPU page size!\n");
                return -EINVAL;
        }
        /* Compute table size */
        rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
-       rdev->gart.num_gpu_pages = rdev->mc.gtt_size / 4096;
+       rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE;
        DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
                 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
        /* Allocate pages table */
index 8e0a875..a0fe623 100644 (file)
@@ -92,6 +92,13 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
        if (r) {
                return r;
        }
+       /* enable msi */
+       rdev->msi_enabled = 0;
+       if (rdev->family >= CHIP_RV380) {
+               int ret = pci_enable_msi(rdev->pdev);
+               if (!ret)
+                       rdev->msi_enabled = 1;
+       }
        drm_irq_install(rdev->ddev);
        rdev->irq.installed = true;
        DRM_INFO("radeon: irq initialized.\n");
@@ -103,5 +110,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
        if (rdev->irq.installed) {
                rdev->irq.installed = false;
                drm_irq_uninstall(rdev->ddev);
+               if (rdev->msi_enabled)
+                       pci_disable_msi(rdev->pdev);
        }
 }
index 36410f8..8d0b7aa 100644 (file)
@@ -48,7 +48,7 @@ static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
        u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active;
        u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp;
        u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp;
-       struct radeon_native_mode *native_mode = &radeon_crtc->native_mode;
+       struct drm_display_mode *native_mode = &radeon_crtc->native_mode;
 
        fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
                (RADEON_VERT_STRETCH_RESERVED |
@@ -95,19 +95,19 @@ static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
 
        fp_horz_vert_active = 0;
 
-       if (native_mode->panel_xres == 0 ||
-           native_mode->panel_yres == 0) {
+       if (native_mode->hdisplay == 0 ||
+           native_mode->vdisplay == 0) {
                hscale = false;
                vscale = false;
        } else {
-               if (xres > native_mode->panel_xres)
-                       xres = native_mode->panel_xres;
-               if (yres > native_mode->panel_yres)
-                       yres = native_mode->panel_yres;
+               if (xres > native_mode->hdisplay)
+                       xres = native_mode->hdisplay;
+               if (yres > native_mode->vdisplay)
+                       yres = native_mode->vdisplay;
 
-               if (xres == native_mode->panel_xres)
+               if (xres == native_mode->hdisplay)
                        hscale = false;
-               if (yres == native_mode->panel_yres)
+               if (yres == native_mode->vdisplay)
                        vscale = false;
        }
 
@@ -119,11 +119,11 @@ static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
                else {
                        inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
                        scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
-                               / native_mode->panel_xres + 1;
+                               / native_mode->hdisplay + 1;
                        fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
                                        RADEON_HORZ_STRETCH_BLEND |
                                        RADEON_HORZ_STRETCH_ENABLE |
-                                       ((native_mode->panel_xres/8-1) << 16));
+                                       ((native_mode->hdisplay/8-1) << 16));
                }
 
                if (!vscale)
@@ -131,11 +131,11 @@ static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
                else {
                        inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
                        scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
-                               / native_mode->panel_yres + 1;
+                               / native_mode->vdisplay + 1;
                        fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
                                        RADEON_VERT_STRETCH_ENABLE |
                                        RADEON_VERT_STRETCH_BLEND |
-                                       ((native_mode->panel_yres-1) << 12));
+                                       ((native_mode->vdisplay-1) << 12));
                }
                break;
        case RMX_CENTER:
@@ -175,8 +175,8 @@ static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
                                                ? RADEON_CRTC_V_SYNC_POL
                                                : 0)));
 
-               fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
-                               (((native_mode->panel_xres / 8) & 0x1ff) << 16));
+               fp_horz_vert_active = (((native_mode->vdisplay) & 0xfff) |
+                               (((native_mode->hdisplay / 8) & 0x1ff) << 16));
                break;
        case RMX_OFF:
        default:
@@ -532,6 +532,10 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                radeon_fb = to_radeon_framebuffer(old_fb);
                radeon_gem_object_unpin(radeon_fb->obj);
        }
+
+       /* Bytes per pixel may have changed */
+       radeon_bandwidth_update(rdev);
+
        return 0;
 }
 
@@ -664,6 +668,9 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
 
                WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl);
                WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+
+               WREG32(RADEON_FP_H2_SYNC_STRT_WID, crtc_h_sync_strt_wid);
+               WREG32(RADEON_FP_V2_SYNC_STRT_WID, crtc_v_sync_strt_wid);
        } else {
                uint32_t crtc_gen_cntl;
                uint32_t crtc_ext_cntl;
@@ -1015,14 +1022,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
                                 int x, int y, struct drm_framebuffer *old_fb)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
 
        /* TODO TV */
        radeon_crtc_set_base(crtc, x, y, old_fb);
        radeon_set_crtc_timing(crtc, adjusted_mode);
        radeon_set_pll(crtc, adjusted_mode);
-       radeon_bandwidth_update(rdev);
        if (radeon_crtc->crtc_id == 0) {
                radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
        } else {
index 6ceb958..0038212 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)
@@ -192,6 +190,8 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
 {
        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)
@@ -218,7 +218,8 @@ static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder,
                                                 struct drm_display_mode *mode,
                                                 struct drm_display_mode *adjusted_mode)
 {
-
+       /* set the active encoder to connector routing */
+       radeon_encoder_set_active_device(encoder);
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        return true;
@@ -272,7 +273,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)
@@ -468,7 +468,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 +542,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 +563,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;
@@ -593,7 +600,8 @@ static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder,
                                              struct drm_display_mode *mode,
                                              struct drm_display_mode *adjusted_mode)
 {
-
+       /* set the active encoder to connector routing */
+       radeon_encoder_set_active_device(encoder);
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        return true;
@@ -636,7 +644,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)
@@ -735,7 +742,8 @@ static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder,
                                            struct drm_display_mode *mode,
                                            struct drm_display_mode *adjusted_mode)
 {
-
+       /* set the active encoder to connector routing */
+       radeon_encoder_set_active_device(encoder);
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        return true;
@@ -839,7 +847,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)
index e612268..ace726a 100644 (file)
@@ -172,6 +172,7 @@ enum radeon_connector_table {
 
 struct radeon_mode_info {
        struct atom_context *atom_context;
+       struct card_info *atom_card_info;
        enum radeon_connector_table connector_table;
        bool mode_config_initialized;
        struct radeon_crtc *crtcs[2];
@@ -186,17 +187,6 @@ struct radeon_mode_info {
 
 };
 
-struct radeon_native_mode {
-       /* preferred mode */
-       uint32_t panel_xres, panel_yres;
-       uint32_t hoverplus, hsync_width;
-       uint32_t hblank;
-       uint32_t voverplus, vsync_width;
-       uint32_t vblank;
-       uint32_t dotclock;
-       uint32_t flags;
-};
-
 #define MAX_H_CODE_TIMING_LEN 32
 #define MAX_V_CODE_TIMING_LEN 32
 
@@ -228,7 +218,7 @@ struct radeon_crtc {
        enum radeon_rmx_type rmx_type;
        fixed20_12 vsc;
        fixed20_12 hsc;
-       struct radeon_native_mode native_mode;
+       struct drm_display_mode native_mode;
 };
 
 struct radeon_encoder_primary_dac {
@@ -248,7 +238,7 @@ struct radeon_encoder_lvds {
        bool     use_bios_dividers;
        uint32_t lvds_gen_cntl;
        /* panel mode */
-       struct radeon_native_mode native_mode;
+       struct drm_display_mode native_mode;
 };
 
 struct radeon_encoder_tv_dac {
@@ -271,6 +261,16 @@ struct radeon_encoder_int_tmds {
        struct radeon_tmds_pll tmds_pll[4];
 };
 
+/* spread spectrum */
+struct radeon_atom_ss {
+       uint16_t percentage;
+       uint8_t type;
+       uint8_t step;
+       uint8_t delay;
+       uint8_t range;
+       uint8_t refdiv;
+};
+
 struct radeon_encoder_atom_dig {
        /* atom dig */
        bool coherent_mode;
@@ -278,8 +278,9 @@ struct radeon_encoder_atom_dig {
        /* atom lvds */
        uint32_t lvds_misc;
        uint16_t panel_pwr_delay;
+       struct radeon_atom_ss *ss;
        /* panel mode */
-       struct radeon_native_mode native_mode;
+       struct drm_display_mode native_mode;
 };
 
 struct radeon_encoder_atom_dac {
@@ -294,7 +295,7 @@ struct radeon_encoder {
        uint32_t flags;
        uint32_t pixel_clock;
        enum radeon_rmx_type rmx_type;
-       struct radeon_native_mode native_mode;
+       struct drm_display_mode native_mode;
        void *enc_priv;
 };
 
@@ -308,12 +309,15 @@ struct radeon_connector {
        uint32_t connector_id;
        uint32_t devices;
        struct radeon_i2c_chan *ddc_bus;
+       /* some systems have a an hdmi and vga port with a shared ddc line */
+       bool shared_ddc;
        bool use_digital;
        /* we need to mind the EDID between detect
           and get modes due to analog/digital/tvencoder */
        struct edid *edid;
        void *con_priv;
        bool dac_load_detect;
+       uint16_t connector_object_id;
 };
 
 struct radeon_framebuffer {
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
new file mode 100644 (file)
index 0000000..46146c6
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
+ */
+#include "drmP.h"
+#include "radeon.h"
+
+int radeon_debugfs_pm_init(struct radeon_device *rdev);
+
+int radeon_pm_init(struct radeon_device *rdev)
+{
+       if (radeon_debugfs_pm_init(rdev)) {
+               DRM_ERROR("Failed to register debugfs file for CP !\n");
+       }
+
+       return 0;
+}
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+
+static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       seq_printf(m, "engine clock: %u0 Hz\n", radeon_get_engine_clock(rdev));
+       seq_printf(m, "memory clock: %u0 Hz\n", radeon_get_memory_clock(rdev));
+
+       return 0;
+}
+
+static struct drm_info_list radeon_pm_info_list[] = {
+       {"radeon_pm_info", radeon_debugfs_pm_info, 0, NULL},
+};
+#endif
+
+int radeon_debugfs_pm_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+       return radeon_debugfs_add_files(rdev, radeon_pm_info_list, ARRAY_SIZE(radeon_pm_info_list));
+#else
+       return 0;
+#endif
+}
index bfa1ab9..29ab759 100644 (file)
 #define RADEON_BUS_CNTL                     0x0030
 #       define RADEON_BUS_MASTER_DIS         (1 << 6)
 #       define RADEON_BUS_BIOS_DIS_ROM       (1 << 12)
+#      define RS600_BUS_MASTER_DIS          (1 << 14)
+#      define RS600_MSI_REARM               (1 << 20) /* rs600/rs690/rs740 */
 #       define RADEON_BUS_RD_DISCARD_EN      (1 << 24)
 #       define RADEON_BUS_RD_ABORT_EN        (1 << 25)
 #       define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28)
 #       define RADEON_BUS_READ_BURST         (1 << 30)
 #define RADEON_BUS_CNTL1                    0x0034
 #       define RADEON_BUS_WAIT_ON_LOCK_EN    (1 << 4)
+/* rv370/rv380, rv410, r423/r430/r480, r5xx */
+#define RADEON_MSI_REARM_EN                0x0160
+#      define RV370_MSI_REARM_EN            (1 << 0)
 
 /* #define RADEON_PCIE_INDEX                   0x0030 */
 /* #define RADEON_PCIE_DATA                    0x0034 */
 #define RADEON_AIC_CNTL                     0x01d0
 #       define RADEON_PCIGART_TRANSLATE_EN     (1 << 0)
 #       define RADEON_DIS_OUT_OF_PCI_GART_ACCESS     (1 << 1)
+#      define RS400_MSI_REARM                  (1 << 3) /* rs400/rs480 */
 #define RADEON_AIC_LO_ADDR                  0x01dc
 #define RADEON_AIC_PT_BASE             0x01d8
 #define RADEON_AIC_HI_ADDR             0x01e0
index 03c33cf..f8a465d 100644 (file)
@@ -42,7 +42,7 @@ void radeon_test_moves(struct radeon_device *rdev)
        /* Number of tests =
         * (Total GTT - IB pool - writeback page - ring buffer) / test size
         */
-       n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - 4096 -
+       n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE -
             rdev->cp.ring_size) / size;
 
        gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
@@ -102,7 +102,7 @@ void radeon_test_moves(struct radeon_device *rdev)
                        goto out_cleanup;
                }
 
-               r = radeon_copy(rdev, gtt_addr, vram_addr, size / 4096, fence);
+               r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, fence);
                if (r) {
                        DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
                        goto out_cleanup;
@@ -145,7 +145,7 @@ void radeon_test_moves(struct radeon_device *rdev)
                        goto out_cleanup;
                }
 
-               r = radeon_copy(rdev, vram_addr, gtt_addr, size / 4096, fence);
+               r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, fence);
                if (r) {
                        DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
                        goto out_cleanup;
index 765bd18..1381e06 100644 (file)
@@ -295,6 +295,12 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
        if (unlikely(r)) {
                return r;
        }
+
+       r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement);
+       if (unlikely(r)) {
+               goto out_cleanup;
+       }
+
        r = ttm_tt_bind(bo->ttm, &tmp_mem);
        if (unlikely(r)) {
                goto out_cleanup;
index a769c29..ca03716 100644 (file)
@@ -418,6 +418,8 @@ int rs400_resume(struct radeon_device *rdev)
        rs400_gart_disable(rdev);
        /* Resume clock before doing reset */
        r300_clock_startup(rdev);
+       /* setup MC before calling post tables */
+       rs400_mc_program(rdev);
        /* Reset gpu before posting otherwise ATOM will enter infinite loop */
        if (radeon_gpu_reset(rdev)) {
                dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
index 10dfa78..5f117cd 100644 (file)
@@ -242,7 +242,7 @@ void rs600_irq_disable(struct radeon_device *rdev)
 
 int rs600_irq_process(struct radeon_device *rdev)
 {
-       uint32_t status;
+       uint32_t status, msi_rearm;
        uint32_t r500_disp_int;
 
        status = rs600_irq_ack(rdev, &r500_disp_int);
@@ -260,6 +260,22 @@ int rs600_irq_process(struct radeon_device *rdev)
                        drm_handle_vblank(rdev->ddev, 1);
                status = rs600_irq_ack(rdev, &r500_disp_int);
        }
+       if (rdev->msi_enabled) {
+               switch (rdev->family) {
+               case CHIP_RS600:
+               case CHIP_RS690:
+               case CHIP_RS740:
+                       msi_rearm = RREG32(RADEON_BUS_CNTL) & ~RS600_MSI_REARM;
+                       WREG32(RADEON_BUS_CNTL, msi_rearm);
+                       WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM);
+                       break;
+               default:
+                       msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm);
+                       WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+                       break;
+               }
+       }
        return IRQ_HANDLED;
 }
 
@@ -472,6 +488,8 @@ int rs600_init(struct radeon_device *rdev)
        }
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Get vram informations */
        rs600_vram_info(rdev);
        /* Initialize memory controller (also test AGP) */
index 025e322..2754717 100644 (file)
@@ -706,6 +706,8 @@ int rs690_init(struct radeon_device *rdev)
        }
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Get vram informations */
        rs690_vram_info(rdev);
        /* Initialize memory controller (also test AGP) */
index 41a34c2..7935f79 100644 (file)
@@ -137,6 +137,8 @@ int rv515_mc_wait_for_idle(struct radeon_device *rdev)
 
 void rv515_vga_render_disable(struct radeon_device *rdev)
 {
+       WREG32(R_000330_D1VGA_CONTROL, 0);
+       WREG32(R_000338_D2VGA_CONTROL, 0);
        WREG32(R_000300_VGA_RENDER_CONTROL,
                RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL);
 }
@@ -585,6 +587,8 @@ int rv515_init(struct radeon_device *rdev)
        }
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Get vram informations */
        rv515_vram_info(rdev);
        /* Initialize memory controller (also test AGP) */
index 595ac63..b0efd0d 100644 (file)
@@ -529,11 +529,11 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        if (rdev->family == CHIP_RV770)
                gb_tiling_config |= BANK_TILING(1);
        else
-               gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_SHIFT) >> NOOFBANK_MASK);
+               gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
 
        gb_tiling_config |= GROUP_SIZE(0);
 
-       if (((mc_arb_ramcfg & NOOFROWS_MASK) & NOOFROWS_SHIFT) > 3) {
+       if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {
                gb_tiling_config |= ROW_TILING(3);
                gb_tiling_config |= SAMPLE_SPLIT(3);
        } else {
@@ -579,14 +579,14 @@ static void rv770_gpu_init(struct radeon_device *rdev)
 
        /* set HW defaults for 3D engine */
        WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) |
-                                               ROQ_IB2_START(0x2b)));
+                                    ROQ_IB2_START(0x2b)));
 
        WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30));
 
        WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO |
-                                       SYNC_GRADIENT |
-                                       SYNC_WALKER |
-                                       SYNC_ALIGNER));
+                            SYNC_GRADIENT |
+                            SYNC_WALKER |
+                            SYNC_ALIGNER));
 
        sx_debug_1 = RREG32(SX_DEBUG_1);
        sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
@@ -598,9 +598,9 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        WREG32(SMX_DC_CTL0, smx_dc_ctl0);
 
        WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
-                                         GS_FLUSH_CTL(4) |
-                                         ACK_FLUSH_CTL(3) |
-                                         SYNC_FLUSH_CTL));
+                              GS_FLUSH_CTL(4) |
+                              ACK_FLUSH_CTL(3) |
+                              SYNC_FLUSH_CTL));
 
        if (rdev->family == CHIP_RV770)
                WREG32(DB_DEBUG3, DB_CLK_OFF_DELAY(0x1f));
@@ -611,12 +611,12 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        }
 
        WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.rv770.sx_max_export_size / 4) - 1) |
-                                                  POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) |
-                                                  SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1)));
+                                       POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) |
+                                       SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1)));
 
        WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.rv770.sc_prim_fifo_size) |
-                                                SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) |
-                                                SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize)));
+                                SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) |
+                                SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize)));
 
        WREG32(PA_SC_MULTI_CHIP_CNTL, 0);
 
@@ -774,14 +774,36 @@ int rv770_mc_init(struct radeon_device *rdev)
 {
        fixed20_12 a;
        u32 tmp;
+       int chansize, numchan;
        int r;
 
        /* Get VRAM informations */
-       /* FIXME: Don't know how to determine vram width, need to check
-        * vram_width usage
-        */
-       rdev->mc.vram_width = 128;
        rdev->mc.vram_is_ddr = true;
+       tmp = RREG32(MC_ARB_RAMCFG);
+       if (tmp & CHANSIZE_OVERRIDE) {
+               chansize = 16;
+       } else if (tmp & CHANSIZE_MASK) {
+               chansize = 64;
+       } else {
+               chansize = 32;
+       }
+       tmp = RREG32(MC_SHARED_CHMAP);
+       switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+       case 0:
+       default:
+               numchan = 1;
+               break;
+       case 1:
+               numchan = 2;
+               break;
+       case 2:
+               numchan = 4;
+               break;
+       case 3:
+               numchan = 8;
+               break;
+       }
+       rdev->mc.vram_width = numchan * chansize;
        /* Could aper size report 0 ? */
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
        rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
@@ -961,10 +983,13 @@ int rv770_init(struct radeon_device *rdev)
        r600_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
        r = radeon_clocks_init(rdev);
        if (r)
                return r;
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
        if (r)
index 4b9c3d6..a1367ab 100644 (file)
 #define HDP_REG_COHERENCY_FLUSH_CNTL                   0x54A0
 #define        HDP_TILING_CONFIG                               0x2F3C
 
+#define MC_SHARED_CHMAP                                                0x2004
+#define                NOOFCHAN_SHIFT                                  12
+#define                NOOFCHAN_MASK                                   0x00003000
+
 #define        MC_ARB_RAMCFG                                   0x2760
 #define                NOOFBANK_SHIFT                                  0
 #define                NOOFBANK_MASK                                   0x00000003
 #define                CHANSIZE_MASK                                   0x00000100
 #define                BURSTLENGTH_SHIFT                               9
 #define                BURSTLENGTH_MASK                                0x00000200
+#define                CHANSIZE_OVERRIDE                               (1 << 11)
 #define        MC_VM_AGP_TOP                                   0x2028
 #define        MC_VM_AGP_BOT                                   0x202C
 #define        MC_VM_AGP_BASE                                  0x2030
index a55ee1a..7bcb89f 100644 (file)
@@ -279,6 +279,7 @@ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement)
 
        return ttm_tt_set_caching(ttm, state);
 }
+EXPORT_SYMBOL(ttm_tt_set_placement_caching);
 
 static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm)
 {