From e33497aaaef5ec9998cf7b007b13d74bb41be74e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 12 Oct 2009 13:32:38 +1000 Subject: drm/radeon/kms: don't refuse LUT because no framebuffer. The fb binding might be happening in a subsequent crtc setup call. gets rid of some lut issues. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 3655d91993a..b8f234497ac 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -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); } -- cgit v1.2.3-70-g09d2 From f30f37def4c72e5df8d949022b806e5a4e99bbcb Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 8 Oct 2009 10:44:09 +0200 Subject: drm/radeon/kms: Update memory bandwidth requirements in mode_set_base hook. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hook may change the number of bytes per pixel being scanned out, which affects the CRTC memory bandwidth requirements. E.g. booting in 8bpp and then running X in 32bpp would result in the bandwidth requirements being underestimated for the latter and consequently in CRTC FIFO underruns causing visible artifacts with 3D intensive workloads. ATOM changes only compile-tested. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 5 ++++- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 14fa9701aeb..38a87cc6eb1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -563,6 +563,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; } @@ -701,7 +705,6 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, } atombios_overscan_setup(crtc, mode, adjusted_mode); atombios_scaler_setup(crtc); - radeon_bandwidth_update(rdev); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 36410f85d70..ec2df739c11 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -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; } @@ -1015,14 +1019,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 { -- cgit v1.2.3-70-g09d2 From b5fc901002db0519093ec723fd98969bc03cd629 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 8 Oct 2009 10:44:10 +0200 Subject: drm/radeon/kms: Fix apparent typo in legacy CRTC memory bandwidth calculation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While investigating the cause of CRTC FIFO underruns, I noticed that when converting the memory bandwidth calculation from the userspace X driver code, an instance of '8.0' was apparently accidentally converted to '80'. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 374ecacc618..33198dd5706 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2350,7 +2350,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; -- cgit v1.2.3-70-g09d2 From 2ffb842948ba64b03986f4064140a74c1780c44b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Oct 2009 13:02:19 -0400 Subject: drm/radeon/kms: make sure LVDS panel is valid in detect() If the panel data is bogus this can lead to problems later when the hardware trys to set the mode. If the data is invalid, report LVDS as disconnected. Should fix fdo bug 24247. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index e376be47a4a..466f6010a2e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -415,8 +415,20 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) { - enum drm_connector_status ret = connector_status_connected; + enum drm_connector_status ret = connector_status_disconnected; + struct drm_encoder *encoder = radeon_best_single_encoder(connector); + + if (encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; + + /* check if panel is valid */ + if (native_mode->panel_xres >= 320 && native_mode->panel_yres >= 240) + ret = connector_status_connected; + + } /* check acpi lid status ??? */ + radeon_connector_update_scratch_regs(connector, ret); return ret; } -- cgit v1.2.3-70-g09d2 From 5f9a0eb5af16906cd31fc3e02746aa3d61fd3aa9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Oct 2009 13:08:29 -0400 Subject: drm/radeon/kms/atom: reorder crtc dpms Based on recommendation from bios docs. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 38a87cc6eb1..0a5082af3cd 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -248,18 +248,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; } -- cgit v1.2.3-70-g09d2 From 2606c88608122339cbd5c6b5c149a2eb74ccfe9e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Oct 2009 13:36:21 -0400 Subject: drm/radeon/kms/atom: add support for AdjustDisplayPll DCE3+ has an AdjustDisplayPll that will adjust the pixel clock accordingly based on the encoder/transmitter to handle special hw requirements. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 36 ++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 0a5082af3cd..d5e6f3da116 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -333,12 +333,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; @@ -393,12 +394,34 @@ 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 + 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); atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, @@ -409,7 +432,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 +445,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 +460,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; @@ -460,6 +483,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) } printk("executing set pll\n"); + index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -- cgit v1.2.3-70-g09d2 From 5a9bcacc0a56f0d9577494e834519480018a6cc3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Oct 2009 15:09:31 -0400 Subject: drm/radeon/kms/atom: rework crtc modeset - clean up tv timing handling - unify SetCRTC_Timing and SetCRTC_UsingDTDTiming Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 221 ++++++++++--------------------- drivers/gpu/drm/radeon/radeon_atombios.c | 93 ++++++++----- drivers/gpu/drm/radeon/radeon_encoders.c | 18 +++ 3 files changed, 148 insertions(+), 184 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index d5e6f3da116..7522af1b9e4 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -270,59 +270,89 @@ 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); } void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) @@ -602,128 +632,17 @@ 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_crtc_set_pll(crtc, adjusted_mode); - atombios_crtc_set_timing(crtc, &crtc_timing); + 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); } diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 5b6c08cee40..979ddfdf209 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -857,8 +857,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 +865,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 +875,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 +914,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; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index a65ab1a0dad..3e58c6eccea 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -31,6 +31,10 @@ 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) { @@ -219,6 +223,8 @@ 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; drm_mode_set_crtcinfo(adjusted_mode, 0); @@ -230,6 +236,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; } -- cgit v1.2.3-70-g09d2 From de2103e452ec7f2db5db7c44279735688608381d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 9 Oct 2009 15:14:30 -0400 Subject: drm/radeon/kms: use drm_mode directly for panel modes This reduces the number of mode format conversions needed and makes native panel mode support cleaner. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 32 ++++++++------- drivers/gpu/drm/radeon/radeon_combios.c | 64 ++++++++++++++--------------- drivers/gpu/drm/radeon/radeon_connectors.c | 55 +++++++++---------------- drivers/gpu/drm/radeon/radeon_display.c | 6 +-- drivers/gpu/drm/radeon/radeon_encoders.c | 50 ++++------------------ drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 30 +++++++------- drivers/gpu/drm/radeon/radeon_mode.h | 19 ++------- 7 files changed, 97 insertions(+), 159 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 979ddfdf209..79d4b771c77 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -798,27 +798,29 @@ 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); encoder->native_mode = lvds->native_mode; } diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 748265a105b..e91aba8530b 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -808,25 +808,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 +846,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 +882,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 +944,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 { diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 466f6010a2e..da3a049e364 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -178,25 +178,13 @@ 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; + struct drm_display_mode *native_mode = &radeon_encoder->native_mode; - if (native_mode->panel_xres != 0 && - native_mode->panel_yres != 0 && - native_mode->dotclock != 0) { + if (native_mode->hdisplay != 0 && + native_mode->vdisplay != 0 && + native_mode->clock != 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; - + *mode = *native_mode; mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; drm_mode_set_name(mode); @@ -210,7 +198,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; @@ -237,10 +225,10 @@ 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_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 +332,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; } @@ -420,10 +403,10 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec if (encoder) { 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; /* check if panel is valid */ - if (native_mode->panel_xres >= 320 && native_mode->panel_yres >= 240) + if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240) ret = connector_status_connected; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b8f234497ac..a20bf43389b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -761,7 +761,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) { @@ -779,10 +779,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); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 3e58c6eccea..a9d4e0ab049 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -171,49 +171,15 @@ 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) { + *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; } } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index ec2df739c11..d22a195cf15 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -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: diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index e61226817cc..3d2631be073 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -186,17 +186,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 +217,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 +237,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 { @@ -279,7 +268,7 @@ struct radeon_encoder_atom_dig { uint32_t lvds_misc; uint16_t panel_pwr_delay; /* panel mode */ - struct radeon_native_mode native_mode; + struct drm_display_mode native_mode; }; struct radeon_encoder_atom_dac { @@ -294,7 +283,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; }; -- cgit v1.2.3-70-g09d2 From 0549a061b545d232d12836f98c7c4965dd83f837 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 9 Oct 2009 18:41:19 -0400 Subject: drm/radeon/kms: also check for edid in lvds detect In case the system has bad native mode info but valid edid. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index da3a049e364..17d5659cff0 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -398,8 +398,10 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) { - enum drm_connector_status ret = connector_status_disconnected; + 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; + bool dret; if (encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -410,6 +412,15 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec ret = connector_status_connected; } + + /* check for edid as well */ + if (radeon_connector->ddc_bus) { + 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; + } /* check acpi lid status ??? */ radeon_connector_update_scratch_regs(connector, ret); -- cgit v1.2.3-70-g09d2 From ceeb50279b3d05eb7ea2b67e90acb2110d09325f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 12 Oct 2009 13:54:10 +1000 Subject: drm/radeon: Revert "drm/r600: avoid assigning vb twice in blit code" This reverts commit 49c458e544ae14514209ed80ea6829ca1b18ddf0. It seems to have some side effects in the non-kms cases. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_blit.c | 10 +++++++--- drivers/gpu/drm/radeon/r600_blit_kms.c | 3 +-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c index dec50108160..d988eece018 100644 --- a/drivers/gpu/drm/radeon/r600_blit.c +++ b/drivers/gpu/drm/radeon/r600_blit.c @@ -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; @@ -775,6 +777,8 @@ r600_blit_swap(struct drm_device *dev, u64 vb_addr; u32 *vb; + vb = r600_nomm_get_vb_ptr(dev); + if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { r600_nomm_put_vb(dev); @@ -783,8 +787,8 @@ r600_blit_swap(struct drm_device *dev, return; set_shaders(dev); + vb = r600_nomm_get_vb_ptr(dev); } - vb = r600_nomm_get_vb_ptr(dev); if (cpp == 4) { cb_format = COLOR_8_8_8_8; diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 93108bb31d1..acae33e2ad5 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -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; -- cgit v1.2.3-70-g09d2 From 39deb2d67515086f08a672e7574716ca0d3883a5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 12 Oct 2009 14:21:19 +1000 Subject: drm/radeon/kms: fix use of index before proper initialisation. With the adjust table introduction, we need to fill out index before getting the table version. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 7522af1b9e4..3409aa3cbee 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -454,6 +454,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) 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); @@ -513,7 +514,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) } printk("executing set pll\n"); - index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -- cgit v1.2.3-70-g09d2 From fb06ca8f8c61dfd7cbfa2092756577ff78a26dcd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 12 Oct 2009 11:25:05 -0400 Subject: drm/radeon/kms: properly handle mode id with native mode changes drm modes are objects with indentifiers. Make sure to preserve the mode id when copying mode params. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 3 +-- drivers/gpu/drm/radeon/radeon_encoders.c | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 17d5659cff0..729207a1e83 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -183,8 +183,7 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode if (native_mode->hdisplay != 0 && native_mode->vdisplay != 0 && native_mode->clock != 0) { - mode = drm_mode_create(dev); - *mode = *native_mode; + mode = drm_mode_duplicate(dev, native_mode); mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; drm_mode_set_name(mode); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index a9d4e0ab049..10845f39124 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -175,11 +175,13 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder, 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->base.id = mode_id; } } -- cgit v1.2.3-70-g09d2 From 9216d44dc13b5e858253f06d83ceea25a9b72f4f Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Sat, 10 Oct 2009 15:20:55 +0800 Subject: drm/i915: disable FBC for Pineview, fixing a boot hang. Pineview doesn't have this FBC mechanism, so this code doesn't apply. Signed-off-by: Shaohua Li Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 3 +-- drivers/gpu/drm/i915/i915_drv.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 92aeb918e0c..e5b138be45f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1227,8 +1227,7 @@ static int i915_load_modeset_init(struct drm_device *dev, goto out; /* Try to set up FBC with a reasonable compressed buffer size */ - if (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev) || IS_GM45(dev)) && - i915_powersave) { + if (I915_HAS_FBC(dev) && i915_powersave) { int cfb_size; /* Try to get an 8M buffer... */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6035d3dae85..0094f185e17 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -981,7 +981,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev)) #define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev)) -#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev))) +#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_GM45(dev)) && !IS_IGD(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) -- cgit v1.2.3-70-g09d2 From a3e17eb8f4080a79738a938abe718be255247a44 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Sat, 10 Oct 2009 10:42:37 +0800 Subject: drm/i915: Set the LVDS_BORDER when using LVDS scaling mode According to the spec the LVDS_BORDER_ENABLE bit decides whether the border data should be included in the active display and data sent to the panel. Border should be used when in VGA centered (un-scaled) mode or when scaling a 4:3 source image to a wide screen panel (typical 16:9). So when the LVDS scaling is used, decide whether the LVDS_BORDER should be enabled or not according to the current scaling mode. At the same time fix the typo error in LVDS center scaling mode. https://bugs.freedesktop.org/show_bug.cgi?id=23789 Signed-off-by: Zhao Yakui tested-by: Zhao Jian Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_display.c | 2 ++ drivers/gpu/drm/i915/intel_lvds.c | 10 +++++++++- 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0094f185e17..17be01e351b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -492,6 +492,8 @@ typedef struct drm_i915_private { struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; } mm; struct sdvo_device_mapping sdvo_mappings[2]; + /* indicate whether the LVDS_BORDER should be enabled or not */ + unsigned int lvds_border_bits; /* Reclocking support */ bool render_reclock_avail; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0466ddbeba3..5f9272459b7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -968,6 +968,8 @@ #define LVDS_PORT_EN (1 << 31) /* Selects pipe B for LVDS data. Must be set on pre-965. */ #define LVDS_PIPEB_SELECT (1 << 30) +/* Enable border for unscaled (or aspect-scaled) display */ +#define LVDS_BORDER_ENABLE (1 << 15) /* * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per * pixel. diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c14240cc00..9efe11761be 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2936,6 +2936,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, lvds = I915_READ(lvds_reg); lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; + /* set the corresponsding LVDS_BORDER bit */ + lvds |= dev_priv->lvds_border_bits; /* Set the B0-B3 data pairs corresponding to whether we're going to * set the DPLLs for dual-channel mode or not. */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 98ae3d73577..089f18c66dd 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -380,7 +380,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, adjusted_mode->crtc_vblank_start + vsync_pos; /* keep the vsync width constant */ adjusted_mode->crtc_vsync_end = - adjusted_mode->crtc_vblank_start + vsync_width; + adjusted_mode->crtc_vsync_start + vsync_width; border = 1; break; case DRM_MODE_SCALE_ASPECT: @@ -525,6 +525,14 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, out: lvds_priv->pfit_control = pfit_control; lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; + /* + * When there exists the border, it means that the LVDS_BORDR + * should be enabled. + */ + if (border) + dev_priv->lvds_border_bits |= LVDS_BORDER_ENABLE; + else + dev_priv->lvds_border_bits &= ~(LVDS_BORDER_ENABLE); /* * XXX: It would be nice to support lower refresh rates on the * panels to reduce power consumption, and perhaps match the -- cgit v1.2.3-70-g09d2 From 06027f9111b9f3244ddc40752428f7847b0b867e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 5 Oct 2009 13:47:26 -0700 Subject: drm/i915: Save and restore the GM45 FBC regs on suspend and resume. This hasn't fixed the regressions we were testing against, but clearly should be required. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_suspend.c | 26 ++++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17be01e351b..1254c4b80e3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -342,6 +342,7 @@ typedef struct drm_i915_private { u32 savePFIT_CONTROL; u32 save_palette_a[256]; u32 save_palette_b[256]; + u32 saveDPFC_CB_BASE; u32 saveFBC_CFB_BASE; u32 saveFBC_LL_BASE; u32 saveFBC_CONTROL; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index bd6d8d91ca9..660c5f36424 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -437,10 +437,14 @@ void i915_save_display(struct drm_device *dev) /* FIXME: save TV & SDVO state */ /* FBC state */ - dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); - dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE); - dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); - dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); + if (IS_GM45(dev)) { + dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE); + } else { + dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); + dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE); + dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); + dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); + } /* VGA state */ dev_priv->saveVGA0 = I915_READ(VGA0); @@ -511,10 +515,16 @@ void i915_restore_display(struct drm_device *dev) /* FIXME: restore TV & SDVO state */ /* FBC info */ - I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); - I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE); - I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2); - I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL); + if (IS_GM45(dev)) { + g4x_disable_fbc(dev); + I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE); + } else { + i8xx_disable_fbc(dev); + I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); + I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE); + I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2); + I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL); + } /* VGA state */ I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); -- cgit v1.2.3-70-g09d2 From 181a5336d6cc836f05507410d66988c483ad0154 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 13 Oct 2009 10:40:52 -0700 Subject: drm/i915: Fix render reclock availability detection. If the device didn't support EDP, we would bail out too soon. Signed-off-by: Andy Lutomirski [anholt: Pulled this patch out of the patch for adding quirks to enable reclocking.] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_bios.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4337414846b..96cd256e60e 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -351,20 +351,18 @@ parse_driver_features(struct drm_i915_private *dev_priv, struct drm_device *dev = dev_priv->dev; struct bdb_driver_features *driver; - /* set default for chips without eDP */ - if (!SUPPORTS_EDP(dev)) { - dev_priv->edp_support = 0; - return; - } - driver = find_section(bdb, BDB_DRIVER_FEATURES); if (!driver) return; - if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) + if (driver && SUPPORTS_EDP(dev) && + driver->lvds_config == BDB_DRIVER_FEATURE_EDP) { dev_priv->edp_support = 1; + } else { + dev_priv->edp_support = 0; + } - if (driver->dual_frequency) + if (driver && driver->dual_frequency) dev_priv->render_reclock_avail = true; } -- cgit v1.2.3-70-g09d2 From c03342fa6d4617a77cb867ee0ec71665d520eb69 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 29 Sep 2009 11:01:23 +0800 Subject: drm/i915: disable powersave feature for Ironlake currently Until we figure out the right setting for powersave features on Ironlake, disable it for now. Also disable watermark update, which has new registers for it on Ironlake too. Signed-off-by: Zhenyu Wang Reviewed-by: Jesse Barnes [anholt: Resolved against the Pineview FBC changes] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 5 ++++- drivers/gpu/drm/i915/intel_display.c | 11 +++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1254c4b80e3..24e154e4722 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -984,7 +984,10 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev)) #define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev)) -#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_GM45(dev)) && !IS_IGD(dev)) +#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \ + (IS_I9XX(dev) || IS_GM45(dev)) && \ + !IS_IGD(dev) && \ + !IS_IGDNG(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9efe11761be..be7fada590d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2586,6 +2586,9 @@ static void intel_update_watermarks(struct drm_device *dev) unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; int enabled = 0, pixel_size = 0; + if (!dev_priv->display.update_wm) + return; + /* Get the clock config from both planes */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { intel_crtc = to_intel_crtc(crtc); @@ -4126,7 +4129,9 @@ void intel_init_clock_gating(struct drm_device *dev) * Disable clock gating reported to work incorrectly according to the * specs, but enable as much else as we can. */ - if (IS_G4X(dev)) { + if (IS_IGDNG(dev)) { + return; + } else if (IS_G4X(dev)) { uint32_t dspclk_gate; I915_WRITE(RENCLK_GATE_D1, 0); I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | @@ -4214,7 +4219,9 @@ static void intel_init_display(struct drm_device *dev) i830_get_display_clock_speed; /* For FIFO watermark updates */ - if (IS_G4X(dev)) + if (IS_IGDNG(dev)) + dev_priv->display.update_wm = NULL; + else if (IS_G4X(dev)) dev_priv->display.update_wm = g4x_update_wm; else if (IS_I965G(dev)) dev_priv->display.update_wm = i965_update_wm; -- cgit v1.2.3-70-g09d2 From 58a27471d00dc09945cbcfbbc5cbcdcd3c28211d Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 25 Sep 2009 08:01:28 +0000 Subject: drm/i915: Fix FDI M/N setting according with correct color depth FDI M/N calculation hasn't taken the current pipe color depth into account, but always set as 24bpp. This one checks current pipe color depth setting, and change FDI M/N calculation a little to use bits_per_pixel first, then convert to bytes_per_pixel later. This fixes display corrupt issue on Arrandle LVDS with 1600x900 panel in 18bpp dual-channel mode. Cc: Stable Team Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 5 +++++ drivers/gpu/drm/i915/intel_display.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5f9272459b7..0dd87a7309e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1782,6 +1782,11 @@ #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) +#define PIPE_BPC_MASK (7 << 5) /* Ironlake */ +#define PIPE_8BPC (0 << 5) +#define PIPE_10BPC (1 << 5) +#define PIPE_6BPC (2 << 5) +#define PIPE_12BPC (3 << 5) #define DSPARB 0x70030 #define DSPARB_CSTART_MASK (0x7f << 7) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index be7fada590d..8278d9d163a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2082,7 +2082,7 @@ fdi_reduce_ratio(u32 *num, u32 *den) #define LINK_N 0x80000 static void -igdng_compute_m_n(int bytes_per_pixel, int nlanes, +igdng_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, int link_clock, struct fdi_m_n *m_n) { @@ -2092,7 +2092,8 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, temp = (u64) DATA_N * pixel_clock; temp = div_u64(temp, link_clock); - m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes); + m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes); + m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */ m_n->gmch_n = DATA_N; fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); @@ -2766,7 +2767,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* FDI link */ if (IS_IGDNG(dev)) { - int lane, link_bw; + int lane, link_bw, bpp; /* eDP doesn't require FDI link, so just set DP M/N according to current link config */ if (is_edp) { @@ -2785,7 +2786,29 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, lane = 4; link_bw = 270000; } - igdng_compute_m_n(3, lane, target_clock, + + /* determine panel color depth */ + temp = I915_READ(pipeconf_reg); + + switch (temp & PIPE_BPC_MASK) { + case PIPE_8BPC: + bpp = 24; + break; + case PIPE_10BPC: + bpp = 30; + break; + case PIPE_6BPC: + bpp = 18; + break; + case PIPE_12BPC: + bpp = 36; + break; + default: + DRM_ERROR("unknown pipe bpc value\n"); + bpp = 24; + } + + igdng_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); } -- cgit v1.2.3-70-g09d2 From 8c2a6d730400e14bf28ccfa11b9bbf453db775ec Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 14 Oct 2009 02:00:42 -0400 Subject: drm/radeon/kms: move active_device setup into encoder fixup() radeon_encoder->active_device defines the active routing between the encoder and connector. The encoder fixup and dpms functions need to know the active_device to function properly. Setting active_device in the prepare hook was too late in some cases. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 19 ++++++------------- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 17 ++++++++--------- 2 files changed, 14 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 10845f39124..6cdef27be99 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -194,6 +194,8 @@ static bool radeon_atom_mode_fixup(struct drm_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) @@ -860,16 +862,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); @@ -900,18 +895,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); @@ -1254,8 +1249,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) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 6ceb958fd19..3a75b5b6009 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -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) @@ -593,7 +592,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 +636,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 +734,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 +839,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) -- cgit v1.2.3-70-g09d2 From 1b4d7d75ccff38008ccd40f8e2d74e33a087caaa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Oct 2009 01:33:35 -0400 Subject: drm/radeon/kms: fix internal tmds setup on legacy display engine - crtc 0 routing was wrong - need to clear various timing bits in FP_GEN_CNTL - need to set FP_H/V2_SYNC_STRT_WID regs for crtc 1 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 3 +++ drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index d22a195cf15..8d0b7aa87fa 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -668,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; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 3a75b5b6009..00382122869 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -542,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 @@ -555,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; -- cgit v1.2.3-70-g09d2 From 0eb96d6ed38430b72897adde58f5477a6b71757a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 14 Oct 2009 12:33:41 -0700 Subject: drm/i915: save/restore BLC histogram control reg across suspend/resume Turns out some machines, like the ThinkPad X40 don't come back if you don't save/restore this register. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/i915_suspend.c | 2 ++ 3 files changed, 5 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 24e154e4722..f6a3587ad06 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -304,6 +304,7 @@ typedef struct drm_i915_private { u32 saveDSPASURF; u32 saveDSPATILEOFF; u32 savePFIT_PGM_RATIOS; + u32 saveBLC_HIST_CTL; u32 saveBLC_PWM_CTL; u32 saveBLC_PWM_CTL2; u32 saveFPB0; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0dd87a7309e..b4813586d92 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1080,6 +1080,8 @@ #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +#define BLC_HIST_CTL 0x61260 + /* TV port control */ #define TV_CTL 0x68000 /** Enables the TV encoder */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 660c5f36424..75c5bed48be 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -410,6 +410,7 @@ void i915_save_display(struct drm_device *dev) dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); if (IS_I965G(dev)) dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); if (IS_MOBILE(dev) && !IS_I830(dev)) @@ -501,6 +502,7 @@ void i915_restore_display(struct drm_device *dev) I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); + I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL); I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); -- cgit v1.2.3-70-g09d2 From 0d9c778978ff268228c095ae737c282c03a5986d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Oct 2009 20:12:46 +0100 Subject: drm/i915: Install a fence register for fbc on g4x To enable framebuffer compression on a g4x, we not only need the buffer to tiled (X only), we also need to hold a fence register for the buffer. Currently we only install a fence register for pre-i965s when setting up the scanout buffer. Rather than adding some convoluted logic to g4x_enable_fbc() to acquire a fence register, and perhaps to g4x_disable_fbc() to release it again, we can extend the acquisition during setup to all chipsets. Signed-off-by: Chris Wilson Cc: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8278d9d163a..123cce1ae47 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1260,9 +1260,11 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - /* Pre-i965 needs to install a fence for tiled scan-out */ - if (!IS_I965G(dev) && - obj_priv->fence_reg == I915_FENCE_REG_NONE && + /* Install a fence for tiled scan-out. Pre-i965 always needs a fence, + * whereas 965+ only requires a fence if using framebuffer compression. + * For simplicity, we always install a fence as the cost is not that onerous. + */ + if (obj_priv->fence_reg == I915_FENCE_REG_NONE && obj_priv->tiling_mode != I915_TILING_NONE) { ret = i915_gem_object_get_fence_reg(obj); if (ret != 0) { -- cgit v1.2.3-70-g09d2 From 0294cf4f7f895ddcf284b1ce7cf27a2c9d7106f7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Oct 2009 16:16:35 -0400 Subject: drm/radeon/kms: fix connector edid handling Based partly on a patch from Christian Koenig - fix several memory leaks in radeon_connector->edid handling - store edid in radeon_connector->edid in detect() or get_modes() - switch hdmi detect code to use radeon_connector->edid - add support for oem boards multiple connectors that share a ddc line. - short circuit lvds_detect() if have a stored edid Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 75 ++++++++++++++++++++++++------ drivers/gpu/drm/radeon/radeon_display.c | 18 ++----- drivers/gpu/drm/radeon/radeon_encoders.c | 10 ++-- drivers/gpu/drm/radeon/radeon_mode.h | 2 + 4 files changed, 73 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 729207a1e83..5b6067aa08b 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -400,7 +400,6 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec 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; - bool dret; if (encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -413,12 +412,17 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec } /* check for edid as well */ - if (radeon_connector->ddc_bus) { - 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; + 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 ??? */ @@ -432,6 +436,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); @@ -519,9 +525,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); @@ -649,6 +678,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); @@ -659,10 +692,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; } } @@ -787,6 +825,7 @@ radeon_add_atom_connector(struct drm_device *dev, 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 */ @@ -800,6 +839,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); @@ -810,6 +856,7 @@ 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; switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index a20bf43389b..c85df4afcb7 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -334,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); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 6cdef27be99..b70440e8d17 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -449,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)) { @@ -474,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; @@ -532,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; @@ -542,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; @@ -554,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; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 3d2631be073..b6868fbe734 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -297,6 +297,8 @@ 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 */ -- cgit v1.2.3-70-g09d2 From ceefedd8e8a80b743fa0b6d6b1992be7029a9efb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Oct 2009 23:57:47 -0400 Subject: drm/radeon/kms/atom: fix tv-out D1MODE_INTERLEAVE_EN was getting set in some cases in the encoder quirks function due to the changes in 5a9bcacc0a56f0d9577494e834519480018a6cc3 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 ---- drivers/gpu/drm/radeon/radeon_encoders.c | 9 ++++++--- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 3409aa3cbee..f7dcb691683 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -31,10 +31,6 @@ #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) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index b70440e8d17..2aa5994a29d 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -206,7 +206,7 @@ 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) { + 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 || @@ -1085,8 +1085,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 -- cgit v1.2.3-70-g09d2 From dfdd646773941bb6b22c3898a26a109e57c872a2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Oct 2009 12:48:44 -0400 Subject: drm/radeon/kms: limit default tv modes to <= 1024x768 fixes fdo bug 24496 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 5b6067aa08b..ce3a785a633 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -223,6 +223,11 @@ 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->hdisplay || common_modes[i].h > native_mode->vdisplay || -- cgit v1.2.3-70-g09d2 From a77f171843d466d4af0d527bcb2d314fafa8afd7 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Wed, 14 Oct 2009 00:34:41 -0400 Subject: drm/radeon/kms: use RADEON_GPU_PAGE_SIZE instead of 4096 Signed-off-by: Matt Turner Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 2 +- drivers/gpu/drm/radeon/r300.c | 2 +- drivers/gpu/drm/radeon/r600.c | 10 +++++----- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_benchmark.c | 4 ++-- drivers/gpu/drm/radeon/radeon_gart.c | 20 ++++++++++---------- drivers/gpu/drm/radeon/radeon_test.c | 6 +++--- 7 files changed, 24 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 33198dd5706..c22adff179a 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -240,7 +240,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); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index e08c4a8974c..2f43ee8e404 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -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); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6b43a95a5fb..1b5aa1fd368 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1269,9 +1269,9 @@ int r600_cp_resume(struct radeon_device *rdev) rb_bufsz = drm_order(rdev->cp.ring_size / 8); #ifdef __BIG_ENDIAN WREG32(CP_RB_CNTL, BUF_SWAP_32BIT | RB_NO_UPDATE | - (drm_order(4096/8) << 8) | rb_bufsz); + (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz); #else - WREG32(CP_RB_CNTL, RB_NO_UPDATE | (drm_order(4096/8) << 8) | rb_bufsz); + WREG32(CP_RB_CNTL, RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz); #endif WREG32(CP_SEM_WAIT_TIMER, 0x4); @@ -1400,7 +1400,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 +1450,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; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3598adca034..8b60e36b20b 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -276,6 +276,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; diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 2e938f7496f..10bd50a7db8 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -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; } diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index a931af065dd..a68d7566178 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -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 */ diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 03c33cf4e14..f8a465d9a1c 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -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; -- cgit v1.2.3-70-g09d2 From f059d2ad69b056aeabad4460f706a3df2f77ce50 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 14 Oct 2009 09:11:25 +0800 Subject: drm: Add the basic check for the detailed timing in EDID Sometimes we will get the incorrect display modeline when parsing the detailed timing in EDID. For example: >hsync/vsync width is zero >sync is beyond the blank. So add the basic check for the detailed timing in EDID to avoid the incorrect display modeline. Signed-off-by: Zhao Yakui Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3c0d2b3aed7..cea665d86dd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -626,6 +626,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; } + /* it is incorrect if hsync/vsync width is zero */ + if (!hsync_pulse_width || !vsync_pulse_width) { + DRM_DEBUG_KMS("Incorrect Detailed timing. " + "Wrong Hsync/Vsync pulse width\n"); + return NULL; + } mode = drm_mode_create(dev); if (!mode) return NULL; @@ -647,6 +653,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->vsync_end = mode->vsync_start + vsync_pulse_width; mode->vtotal = mode->vdisplay + vblank; + /* perform the basic check for the detailed timing */ + if (mode->hsync_end > mode->htotal || + mode->vsync_end > mode->vtotal) { + drm_mode_destroy(dev, mode); + DRM_DEBUG_KMS("Incorrect detailed timing. " + "Sync is beyond the blank.\n"); + return NULL; + } + drm_mode_set_name(mode); if (pt->misc & DRM_EDID_PT_INTERLACED) -- cgit v1.2.3-70-g09d2 From 2d152c6ba81c8a7776103b517fa454b8da0419aa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Oct 2009 23:08:05 -0400 Subject: drm/radeon/kms: fix legacy quirk handling Need to check the return type for the quirk function to decide whether we add the connectors and encoders. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index e91aba8530b..3c402b957f0 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1626,8 +1626,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: -- cgit v1.2.3-70-g09d2 From d0c403e950d449c8c413a1fbf05dfec45ce03e55 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Oct 2009 23:38:32 -0400 Subject: drm/radeon/kms: fix support for original r100 Original radeon didn't have a connector table in the bios. Check for the CRT table and if we have one, add a VGA connector. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 3c402b957f0..8298c990be7 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1773,8 +1773,25 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) DRM_MODE_CONNECTOR_DVII, &ddc_i2c); } 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); + } else { + DRM_DEBUG("No connector info found\n"); + return false; + } } } -- cgit v1.2.3-70-g09d2 From c038e51e841581cc3fb9a76e5e16331331e9c85c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 19 Oct 2009 15:43:48 +0800 Subject: drm/i915: fix to setup display reference clock control on Ironlake For new stepping of PCH, the display reference clock is fully under driver's control. This one trys to setup all needed reference clock for different outputs. Older stepping of PCH chipset should be ignoring this. This fixes output failure issue on newer PCH which requires driver to take control of reference clock enabling. Cc: Stable Team Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b4813586d92..cd0ffa015c2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2158,11 +2158,11 @@ #define DREF_CPU_SOURCE_OUTPUT_MASK (3<<13) #define DREF_SSC_SOURCE_DISABLE (0<<11) #define DREF_SSC_SOURCE_ENABLE (2<<11) -#define DREF_SSC_SOURCE_MASK (2<<11) +#define DREF_SSC_SOURCE_MASK (3<<11) #define DREF_NONSPREAD_SOURCE_DISABLE (0<<9) #define DREF_NONSPREAD_CK505_ENABLE (1<<9) #define DREF_NONSPREAD_SOURCE_ENABLE (2<<9) -#define DREF_NONSPREAD_SOURCE_MASK (2<<9) +#define DREF_NONSPREAD_SOURCE_MASK (3<<9) #define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7) #define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7) #define DREF_SSC4_DOWNSPREAD (0<<6) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 123cce1ae47..db4c3870095 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2814,6 +2814,46 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, link_bw, &m_n); } + /* Ironlake: try to setup display ref clock before DPLL + * enabling. This is only under driver's control after + * PCH B stepping, previous chipset stepping should be + * ignoring this setting. + */ + if (IS_IGDNG(dev)) { + temp = I915_READ(PCH_DREF_CONTROL); + /* Always enable nonspread source */ + temp &= ~DREF_NONSPREAD_SOURCE_MASK; + temp |= DREF_NONSPREAD_SOURCE_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + + temp &= ~DREF_SSC_SOURCE_MASK; + temp |= DREF_SSC_SOURCE_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + + udelay(200); + + if (is_edp) { + if (dev_priv->lvds_use_ssc) { + temp |= DREF_SSC1_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + + udelay(200); + + temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + } else { + temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + } + } + } + if (IS_IGD(dev)) { fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; if (has_reduced_clock) -- cgit v1.2.3-70-g09d2 From b1f60b7029989da71fd8ea1b1176480fac9e846c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 19 Oct 2009 15:43:49 +0800 Subject: drm/i915: fix panel fitting filter coefficient select for Ironlake Must set filter selection as hardcoded coefficients for medium 3x3 filtering, which matches vbios setting for Ironlake. This fixes display corrupt issue on HP arrandale with new vbios. Cc: Stable Team Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 5 +++++ drivers/gpu/drm/i915/intel_display.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cd0ffa015c2..78f336e0083 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2039,6 +2039,11 @@ #define PFA_CTL_1 0x68080 #define PFB_CTL_1 0x68880 #define PF_ENABLE (1<<31) +#define PF_FILTER_MASK (3<<23) +#define PF_FILTER_PROGRAMMED (0<<23) +#define PF_FILTER_MED_3x3 (1<<23) +#define PF_FILTER_EDGE_ENHANCE (2<<23) +#define PF_FILTER_EDGE_SOFTEN (3<<23) #define PFA_WIN_SZ 0x68074 #define PFB_WIN_SZ 0x68874 #define PFA_WIN_POS 0x68070 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index db4c3870095..e189fd6dedc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1515,7 +1515,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) /* Enable panel fitting for LVDS */ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { temp = I915_READ(pf_ctl_reg); - I915_WRITE(pf_ctl_reg, temp | PF_ENABLE); + I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3); /* currently full aspect */ I915_WRITE(pf_win_pos, 0); -- cgit v1.2.3-70-g09d2 From d54e9d28241fd52cca3df4f6bc2054a30d453fed Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 19 Oct 2009 15:43:51 +0800 Subject: drm/i915: quiet DP i2c init Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f4856a51047..d83447557f9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -400,7 +400,7 @@ intel_dp_i2c_init(struct intel_output *intel_output, const char *name) { struct intel_dp_priv *dp_priv = intel_output->dev_priv; - DRM_ERROR("i2c_init %s\n", name); + DRM_DEBUG_KMS("i2c_init %s\n", name); dp_priv->algo.running = false; dp_priv->algo.address = 0; dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch; -- cgit v1.2.3-70-g09d2 From 0e442c60dd39ac6924b11a20497734bd2303744c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 19 Oct 2009 10:09:33 +0900 Subject: drm/i915: add FIFO watermark support for G4x Turns out G4x needs to have sensible watermarks set, especially for self-refresh enabled modes. Add support for it. Signed-off-by: Jesse Barnes Tested-by: Dirk Hohndel Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 12 ++++++ drivers/gpu/drm/i915/intel_display.c | 80 ++++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 78f336e0083..1687edf6879 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1799,17 +1799,29 @@ #define DSPARB_AEND_SHIFT 0 #define DSPFW1 0x70034 +#define DSPFW_SR_SHIFT 23 +#define DSPFW_CURSORB_SHIFT 16 +#define DSPFW_PLANEB_SHIFT 8 #define DSPFW2 0x70038 +#define DSPFW_CURSORA_MASK 0x00003f00 +#define DSPFW_CURSORA_SHIFT 16 #define DSPFW3 0x7003c +#define DSPFW_HPLL_SR_EN (1<<31) +#define DSPFW_CURSOR_SR_SHIFT 24 #define IGD_SELF_REFRESH_EN (1<<30) /* FIFO watermark sizes etc */ +#define G4X_FIFO_LINE_SIZE 64 #define I915_FIFO_LINE_SIZE 64 #define I830_FIFO_LINE_SIZE 32 + +#define G4X_FIFO_SIZE 127 #define I945_FIFO_SIZE 127 /* 945 & 965 */ #define I915_FIFO_SIZE 95 #define I855GM_FIFO_SIZE 127 /* In cachelines */ #define I830_FIFO_SIZE 95 + +#define G4X_MAX_WM 0x3f #define I915_MAX_WM 0x3f #define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e189fd6dedc..47d6ff05899 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2143,6 +2143,13 @@ static struct intel_watermark_params igd_cursor_hplloff_wm = { IGD_CURSOR_GUARD_WM, IGD_FIFO_LINE_SIZE }; +static struct intel_watermark_params g4x_wm_info = { + G4X_FIFO_SIZE, + G4X_MAX_WM, + G4X_MAX_WM, + 2, + G4X_FIFO_LINE_SIZE, +}; static struct intel_watermark_params i945_wm_info = { I945_FIFO_SIZE, I915_MAX_WM, @@ -2433,17 +2440,74 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) return size; } -static void g4x_update_wm(struct drm_device *dev, int unused, int unused2, - int unused3, int unused4) +static void g4x_update_wm(struct drm_device *dev, int planea_clock, + int planeb_clock, int sr_hdisplay, int pixel_size) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 fw_blc_self = I915_READ(FW_BLC_SELF); + int total_size, cacheline_size; + int planea_wm, planeb_wm, cursora_wm, cursorb_wm, cursor_sr; + struct intel_watermark_params planea_params, planeb_params; + unsigned long line_time_us; + int sr_clock, sr_entries = 0, entries_required; - if (i915_powersave) - fw_blc_self |= FW_BLC_SELF_EN; - else - fw_blc_self &= ~FW_BLC_SELF_EN; - I915_WRITE(FW_BLC_SELF, fw_blc_self); + /* Create copies of the base settings for each pipe */ + planea_params = planeb_params = g4x_wm_info; + + /* Grab a couple of global values before we overwrite them */ + total_size = planea_params.fifo_size; + cacheline_size = planea_params.cacheline_size; + + /* + * Note: we need to make sure we don't overflow for various clock & + * latency values. + * clocks go from a few thousand to several hundred thousand. + * latency is usually a few thousand + */ + entries_required = ((planea_clock / 1000) * pixel_size * latency_ns) / + 1000; + entries_required /= G4X_FIFO_LINE_SIZE; + planea_wm = entries_required + planea_params.guard_size; + + entries_required = ((planeb_clock / 1000) * pixel_size * latency_ns) / + 1000; + entries_required /= G4X_FIFO_LINE_SIZE; + planeb_wm = entries_required + planeb_params.guard_size; + + cursora_wm = cursorb_wm = 16; + cursor_sr = 32; + + DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); + + /* Calc sr entries for one plane configs */ + if (sr_hdisplay && (!planea_clock || !planeb_clock)) { + /* self-refresh has much higher latency */ + const static int sr_latency_ns = 12000; + + sr_clock = planea_clock ? planea_clock : planeb_clock; + line_time_us = ((sr_hdisplay * 1000) / sr_clock); + + /* Use ns/us then divide to preserve precision */ + sr_entries = (((sr_latency_ns / line_time_us) + 1) * + pixel_size * sr_hdisplay) / 1000; + sr_entries = roundup(sr_entries / cacheline_size, 1); + DRM_DEBUG("self-refresh entries: %d\n", sr_entries); + I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + } + + DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", + planea_wm, planeb_wm, sr_entries); + + planea_wm &= 0x3f; + planeb_wm &= 0x3f; + + I915_WRITE(DSPFW1, (sr_entries << DSPFW_SR_SHIFT) | + (cursorb_wm << DSPFW_CURSORB_SHIFT) | + (planeb_wm << DSPFW_PLANEB_SHIFT) | planea_wm); + I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) | + (cursora_wm << DSPFW_CURSORA_SHIFT)); + /* HPLL off in SR has some issues on G4x... disable it */ + I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) | + (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } static void i965_update_wm(struct drm_device *dev, int unused, int unused2, -- cgit v1.2.3-70-g09d2 From 629598da932cfa5ff398fe10bc123282a6f3049e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 20 Oct 2009 07:37:32 +0900 Subject: drm/i915: update watermarks before enabling PLLs When coming back from DPMS or turning on a display, make sure we have the watermarks set up before turning on the display plane, otherwise we may get underruns. Signed-off-by: Jesse Barnes Tested-by: Dirk Hohndel Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 47d6ff05899..7eed3db5451 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1803,6 +1803,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: + intel_update_watermarks(dev); + /* Enable the DPLL */ temp = I915_READ(dpll_reg); if ((temp & DPLL_VCO_ENABLE) == 0) { @@ -1840,7 +1842,6 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) /* Give the overlay scaler a chance to enable if it's on this pipe */ //intel_crtc_dpms_video(crtc, true); TODO - intel_update_watermarks(dev); break; case DRM_MODE_DPMS_OFF: intel_update_watermarks(dev); -- cgit v1.2.3-70-g09d2 From fe798b9718bea5c48938fc38fa78ae9503b8de6c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 20 Oct 2009 07:55:28 +0900 Subject: drm/i915: kill warning in intel_find_pll_g4x_dp Initialize clock.vco to silence gcc. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7eed3db5451..3ba6546b7c7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -943,6 +943,7 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); clock.p = (clock.p1 * clock.p2); clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; + clock.vco = 0; memcpy(best_clock, &clock, sizeof(intel_clock_t)); return true; } -- cgit v1.2.3-70-g09d2 From 4204878179c99d419d392d78d817729992b4c442 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 21 Oct 2009 15:27:01 +0800 Subject: drm/i915: Ironlake suspend/resume support This adds registers save/restore for Ironlake to make suspend work. Signed-off-by: Guo, Chaohong [zhenyuw: some code re-orgnization, and add more save/restore for FDI link and transcoder registers, also fix palette register for Ironlake] Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 30 ++++ drivers/gpu/drm/i915/i915_suspend.c | 281 +++++++++++++++++++++++++++++------- 2 files changed, 256 insertions(+), 55 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f6a3587ad06..9c67f0650a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -296,6 +296,12 @@ typedef struct drm_i915_private { u32 saveVBLANK_A; u32 saveVSYNC_A; u32 saveBCLRPAT_A; + u32 saveTRANS_HTOTAL_A; + u32 saveTRANS_HBLANK_A; + u32 saveTRANS_HSYNC_A; + u32 saveTRANS_VTOTAL_A; + u32 saveTRANS_VBLANK_A; + u32 saveTRANS_VSYNC_A; u32 savePIPEASTAT; u32 saveDSPASTRIDE; u32 saveDSPASIZE; @@ -307,6 +313,8 @@ typedef struct drm_i915_private { u32 saveBLC_HIST_CTL; u32 saveBLC_PWM_CTL; u32 saveBLC_PWM_CTL2; + u32 saveBLC_CPU_PWM_CTL; + u32 saveBLC_CPU_PWM_CTL2; u32 saveFPB0; u32 saveFPB1; u32 saveDPLL_B; @@ -318,6 +326,12 @@ typedef struct drm_i915_private { u32 saveVBLANK_B; u32 saveVSYNC_B; u32 saveBCLRPAT_B; + u32 saveTRANS_HTOTAL_B; + u32 saveTRANS_HBLANK_B; + u32 saveTRANS_HSYNC_B; + u32 saveTRANS_VTOTAL_B; + u32 saveTRANS_VBLANK_B; + u32 saveTRANS_VSYNC_B; u32 savePIPEBSTAT; u32 saveDSPBSTRIDE; u32 saveDSPBSIZE; @@ -351,6 +365,12 @@ typedef struct drm_i915_private { u32 saveIER; u32 saveIIR; u32 saveIMR; + u32 saveDEIER; + u32 saveDEIMR; + u32 saveGTIER; + u32 saveGTIMR; + u32 saveFDI_RXA_IMR; + u32 saveFDI_RXB_IMR; u32 saveCACHE_MODE_0; u32 saveD_STATE; u32 saveDSPCLK_GATE_D; @@ -384,6 +404,16 @@ typedef struct drm_i915_private { u32 savePIPEB_DP_LINK_M; u32 savePIPEA_DP_LINK_N; u32 savePIPEB_DP_LINK_N; + u32 saveFDI_RXA_CTL; + u32 saveFDI_TXA_CTL; + u32 saveFDI_RXB_CTL; + u32 saveFDI_TXB_CTL; + u32 savePFA_CTL_1; + u32 savePFB_CTL_1; + u32 savePFA_WIN_SZ; + u32 savePFB_WIN_SZ; + u32 savePFA_WIN_POS; + u32 savePFB_WIN_POS; struct { struct drm_mm gtt_space; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 75c5bed48be..992d5617e79 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -32,11 +32,15 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 dpll_reg; - if (pipe == PIPE_A) - return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE); - else - return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE); + if (IS_IGDNG(dev)) { + dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B; + } else { + dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B; + } + + return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE); } static void i915_save_palette(struct drm_device *dev, enum pipe pipe) @@ -49,6 +53,9 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe) if (!i915_pipe_enabled(dev, pipe)) return; + if (IS_IGDNG(dev)) + reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; + if (pipe == PIPE_A) array = dev_priv->save_palette_a; else @@ -68,6 +75,9 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) if (!i915_pipe_enabled(dev, pipe)) return; + if (IS_IGDNG(dev)) + reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; + if (pipe == PIPE_A) array = dev_priv->save_palette_a; else @@ -232,10 +242,16 @@ static void i915_save_modeset_reg(struct drm_device *dev) /* Pipe & plane A info */ dev_priv->savePIPEACONF = I915_READ(PIPEACONF); dev_priv->savePIPEASRC = I915_READ(PIPEASRC); - dev_priv->saveFPA0 = I915_READ(FPA0); - dev_priv->saveFPA1 = I915_READ(FPA1); - dev_priv->saveDPLL_A = I915_READ(DPLL_A); - if (IS_I965G(dev)) + if (IS_IGDNG(dev)) { + dev_priv->saveFPA0 = I915_READ(PCH_FPA0); + dev_priv->saveFPA1 = I915_READ(PCH_FPA1); + dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A); + } else { + dev_priv->saveFPA0 = I915_READ(FPA0); + dev_priv->saveFPA1 = I915_READ(FPA1); + dev_priv->saveDPLL_A = I915_READ(DPLL_A); + } + if (IS_I965G(dev) && !IS_IGDNG(dev)) dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); @@ -243,7 +259,24 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A); dev_priv->saveVBLANK_A = I915_READ(VBLANK_A); dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); - dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); + if (!IS_IGDNG(dev)) + dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); + + if (IS_IGDNG(dev)) { + dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL); + dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL); + + dev_priv->savePFA_CTL_1 = I915_READ(PFA_CTL_1); + dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ); + dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS); + + dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A); + dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A); + dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A); + dev_priv->saveTRANS_VTOTAL_A = I915_READ(TRANS_VTOTAL_A); + dev_priv->saveTRANS_VBLANK_A = I915_READ(TRANS_VBLANK_A); + dev_priv->saveTRANS_VSYNC_A = I915_READ(TRANS_VSYNC_A); + } dev_priv->saveDSPACNTR = I915_READ(DSPACNTR); dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE); @@ -260,10 +293,16 @@ static void i915_save_modeset_reg(struct drm_device *dev) /* Pipe & plane B info */ dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); - dev_priv->saveFPB0 = I915_READ(FPB0); - dev_priv->saveFPB1 = I915_READ(FPB1); - dev_priv->saveDPLL_B = I915_READ(DPLL_B); - if (IS_I965G(dev)) + if (IS_IGDNG(dev)) { + dev_priv->saveFPB0 = I915_READ(PCH_FPB0); + dev_priv->saveFPB1 = I915_READ(PCH_FPB1); + dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B); + } else { + dev_priv->saveFPB0 = I915_READ(FPB0); + dev_priv->saveFPB1 = I915_READ(FPB1); + dev_priv->saveDPLL_B = I915_READ(DPLL_B); + } + if (IS_I965G(dev) && !IS_IGDNG(dev)) dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); @@ -271,7 +310,24 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); - dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); + if (!IS_IGDNG(dev)) + dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B); + + if (IS_IGDNG(dev)) { + dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL); + dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL); + + dev_priv->savePFB_CTL_1 = I915_READ(PFB_CTL_1); + dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ); + dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS); + + dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B); + dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B); + dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B); + dev_priv->saveTRANS_VTOTAL_B = I915_READ(TRANS_VTOTAL_B); + dev_priv->saveTRANS_VBLANK_B = I915_READ(TRANS_VBLANK_B); + dev_priv->saveTRANS_VSYNC_B = I915_READ(TRANS_VSYNC_B); + } dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR); dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE); @@ -290,23 +346,41 @@ static void i915_save_modeset_reg(struct drm_device *dev) static void i915_restore_modeset_reg(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + int dpll_a_reg, fpa0_reg, fpa1_reg; + int dpll_b_reg, fpb0_reg, fpb1_reg; if (drm_core_check_feature(dev, DRIVER_MODESET)) return; + if (IS_IGDNG(dev)) { + dpll_a_reg = PCH_DPLL_A; + dpll_b_reg = PCH_DPLL_B; + fpa0_reg = PCH_FPA0; + fpb0_reg = PCH_FPB0; + fpa1_reg = PCH_FPA1; + fpb1_reg = PCH_FPB1; + } else { + dpll_a_reg = DPLL_A; + dpll_b_reg = DPLL_B; + fpa0_reg = FPA0; + fpb0_reg = FPB0; + fpa1_reg = FPA1; + fpb1_reg = FPB1; + } + /* Pipe & plane A info */ /* Prime the clock */ if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { - I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & + I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE); DRM_UDELAY(150); } - I915_WRITE(FPA0, dev_priv->saveFPA0); - I915_WRITE(FPA1, dev_priv->saveFPA1); + I915_WRITE(fpa0_reg, dev_priv->saveFPA0); + I915_WRITE(fpa1_reg, dev_priv->saveFPA1); /* Actually enable it */ - I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); + I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); DRM_UDELAY(150); - if (IS_I965G(dev)) + if (IS_I965G(dev) && !IS_IGDNG(dev)) I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); DRM_UDELAY(150); @@ -317,7 +391,24 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); - I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); + if (!IS_IGDNG(dev)) + I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); + + if (IS_IGDNG(dev)) { + I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL); + I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL); + + I915_WRITE(PFA_CTL_1, dev_priv->savePFA_CTL_1); + I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ); + I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS); + + I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A); + I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A); + I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A); + I915_WRITE(TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A); + I915_WRITE(TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A); + I915_WRITE(TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A); + } /* Restore plane info */ I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); @@ -339,14 +430,14 @@ static void i915_restore_modeset_reg(struct drm_device *dev) /* Pipe & plane B info */ if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { - I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & + I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE); DRM_UDELAY(150); } - I915_WRITE(FPB0, dev_priv->saveFPB0); - I915_WRITE(FPB1, dev_priv->saveFPB1); + I915_WRITE(fpb0_reg, dev_priv->saveFPB0); + I915_WRITE(fpb1_reg, dev_priv->saveFPB1); /* Actually enable it */ - I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); + I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); DRM_UDELAY(150); if (IS_I965G(dev)) I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); @@ -359,7 +450,24 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); - I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); + if (!IS_IGDNG(dev)) + I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); + + if (IS_IGDNG(dev)) { + I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL); + I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL); + + I915_WRITE(PFB_CTL_1, dev_priv->savePFB_CTL_1); + I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ); + I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS); + + I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B); + I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B); + I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B); + I915_WRITE(TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B); + I915_WRITE(TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B); + I915_WRITE(TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B); + } /* Restore plane info */ I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); @@ -404,22 +512,43 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveCURSIZE = I915_READ(CURSIZE); /* CRT state */ - dev_priv->saveADPA = I915_READ(ADPA); + if (IS_IGDNG(dev)) { + dev_priv->saveADPA = I915_READ(PCH_ADPA); + } else { + dev_priv->saveADPA = I915_READ(ADPA); + } /* LVDS state */ - dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); - dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); - dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); - if (IS_I965G(dev)) - dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); - if (IS_MOBILE(dev) && !IS_I830(dev)) - dev_priv->saveLVDS = I915_READ(LVDS); - if (!IS_I830(dev) && !IS_845G(dev)) + if (IS_IGDNG(dev)) { + dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL); + dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); + dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); + dev_priv->saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL); + dev_priv->saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); + dev_priv->saveLVDS = I915_READ(PCH_LVDS); + } else { + dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); + dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); + dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); + dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); + if (IS_I965G(dev)) + dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); + if (IS_MOBILE(dev) && !IS_I830(dev)) + dev_priv->saveLVDS = I915_READ(LVDS); + } + + if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev)) dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); - dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); - dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); - dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); + + if (IS_IGDNG(dev)) { + dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); + dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); + dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); + } else { + dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); + dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); + dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); + } /* Display Port state */ if (SUPPORTS_INTEGRATED_DP(dev)) { @@ -451,7 +580,10 @@ void i915_save_display(struct drm_device *dev) dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA_PD = I915_READ(VGA_PD); - dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); + if (IS_IGDNG(dev)) + dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL); + else + dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); i915_save_vga(dev); } @@ -490,23 +622,41 @@ void i915_restore_display(struct drm_device *dev) I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); /* CRT state */ - I915_WRITE(ADPA, dev_priv->saveADPA); + if (IS_IGDNG(dev)) + I915_WRITE(PCH_ADPA, dev_priv->saveADPA); + else + I915_WRITE(ADPA, dev_priv->saveADPA); /* LVDS state */ - if (IS_I965G(dev)) + if (IS_I965G(dev) && !IS_IGDNG(dev)) I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); - if (IS_MOBILE(dev) && !IS_I830(dev)) + + if (IS_IGDNG(dev)) { + I915_WRITE(PCH_LVDS, dev_priv->saveLVDS); + } else if (IS_MOBILE(dev) && !IS_I830(dev)) I915_WRITE(LVDS, dev_priv->saveLVDS); - if (!IS_I830(dev) && !IS_845G(dev)) + + if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev)) I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); - I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); - I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); - I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL); - I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); - I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); - I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); - I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + if (IS_IGDNG(dev)) { + I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL); + I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL); + I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2); + I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); + I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); + I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR); + I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL); + } else { + I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); + I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); + I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL); + I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); + I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); + I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); + I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + } /* Display Port state */ if (SUPPORTS_INTEGRATED_DP(dev)) { @@ -529,7 +679,10 @@ void i915_restore_display(struct drm_device *dev) } /* VGA state */ - I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); + if (IS_IGDNG(dev)) + I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL); + else + I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); I915_WRITE(VGA0, dev_priv->saveVGA0); I915_WRITE(VGA1, dev_priv->saveVGA1); I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); @@ -555,8 +708,17 @@ int i915_save_state(struct drm_device *dev) i915_save_display(dev); /* Interrupt state */ - dev_priv->saveIER = I915_READ(IER); - dev_priv->saveIMR = I915_READ(IMR); + if (IS_IGDNG(dev)) { + dev_priv->saveDEIER = I915_READ(DEIER); + dev_priv->saveDEIMR = I915_READ(DEIMR); + dev_priv->saveGTIER = I915_READ(GTIER); + dev_priv->saveGTIMR = I915_READ(GTIMR); + dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR); + dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR); + } else { + dev_priv->saveIER = I915_READ(IER); + dev_priv->saveIMR = I915_READ(IMR); + } /* Clock gating state */ dev_priv->saveD_STATE = I915_READ(D_STATE); @@ -621,8 +783,17 @@ int i915_restore_state(struct drm_device *dev) i915_restore_display(dev); /* Interrupt state */ - I915_WRITE (IER, dev_priv->saveIER); - I915_WRITE (IMR, dev_priv->saveIMR); + if (IS_IGDNG(dev)) { + I915_WRITE(DEIER, dev_priv->saveDEIER); + I915_WRITE(DEIMR, dev_priv->saveDEIMR); + I915_WRITE(GTIER, dev_priv->saveGTIER); + I915_WRITE(GTIMR, dev_priv->saveGTIMR); + I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR); + I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR); + } else { + I915_WRITE (IER, dev_priv->saveIER); + I915_WRITE (IMR, dev_priv->saveIMR); + } /* Clock gating state */ I915_WRITE (D_STATE, dev_priv->saveD_STATE); -- cgit v1.2.3-70-g09d2 From c850cb782626fda78e5e9e5baf18a5bd806a225c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 23 Oct 2009 18:49:03 +1000 Subject: drm/kms: fix kms/fbdev colormap support properly. This sets the fbcon to use TRUECOLOR by default, it then only modifies the pseudo palette for fbcon, and only touches the real palette when in 8-bit pseudo color mode. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 23dc9c115fd..9c924614c41 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -454,22 +454,39 @@ out_free: } EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); -static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, +static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; int pindex; + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *palette; + u32 value; + /* place color in psuedopalette */ + if (regno > 16) + return -EINVAL; + palette = (u32 *)info->pseudo_palette; + red >>= (16 - info->var.red.length); + green >>= (16 - info->var.green.length); + blue >>= (16 - info->var.blue.length); + value = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + palette[regno] = value; + return 0; + } + pindex = regno; if (fb->bits_per_pixel == 16) { pindex = regno << 3; if (fb->depth == 16 && regno > 63) - return; + return -EINVAL; if (fb->depth == 15 && regno > 31) - return; + return -EINVAL; if (fb->depth == 16) { u16 r, g, b; @@ -493,13 +510,7 @@ static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, if (fb->depth != 16) fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex); - - if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - ((u32 *) fb->pseudo_palette)[regno] = - (regno << info->var.red.offset) | - (regno << info->var.green.offset) | - (regno << info->var.blue.offset); - } + return 0; } int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) @@ -536,7 +547,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) if (transp) htransp = *transp++; - setcolreg(crtc, hred, hgreen, hblue, start++, info); + rc = setcolreg(crtc, hred, hgreen, hblue, start++, info); + if (rc) + return rc; } crtc_funcs->load_lut(crtc); } @@ -555,6 +568,7 @@ int drm_fb_helper_setcolreg(unsigned regno, struct drm_device *dev = fb_helper->dev; struct drm_crtc *crtc; int i; + int ret; if (regno > 255) return 1; @@ -568,8 +582,10 @@ int drm_fb_helper_setcolreg(unsigned regno, if (i == fb_helper->crtc_count) continue; + ret = setcolreg(crtc, red, green, blue, regno, info); + if (ret) + return ret; - setcolreg(crtc, red, green, blue, regno, info); crtc_funcs->load_lut(crtc); } return 0; @@ -928,7 +944,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, { info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : - FB_VISUAL_DIRECTCOLOR; + FB_VISUAL_TRUECOLOR; info->fix.type_aux = 0; info->fix.xpanstep = 1; /* doing it in hw */ info->fix.ypanstep = 1; /* doing it in hw */ -- cgit v1.2.3-70-g09d2 From ceb776bc87280eb8d13f38e4d7afae757e95af44 Mon Sep 17 00:00:00 2001 From: Mathias Fröhlich Date: Mon, 19 Oct 2009 12:50:41 -0400 Subject: drm/radeon/kms: fix cs parser tex bit 11 check The problem boils down to the order when the bit11 of the texture size is or'ed to the original width. In the end each mipmap level has the same width or height because of that 11 bit is ored to the scaled down lod with and thus blows up the size again to the full size or more due to the power of two rounding afterwards. The attached patch changes this order so that the texture sizes are computed correct. Also the on error the yet missing inputs to the size computation are printed which helped me to find out where it really breaks. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c22adff179a..ed5e983d21e 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2548,8 +2548,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); @@ -2609,15 +2612,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; -- cgit v1.2.3-70-g09d2 From 5885b7a9f4d2a0405b7e42d44eab4ed2302a8239 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 19 Oct 2009 17:23:33 -0400 Subject: drm/radeon/kms: fix vram_width calculation on r6xx/r7xx Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 29 +++++++++++++++++------------ drivers/gpu/drm/radeon/r600d.h | 4 ++++ drivers/gpu/drm/radeon/rv770.c | 30 ++++++++++++++++++++++++++---- drivers/gpu/drm/radeon/rv770d.h | 5 +++++ 4 files changed, 52 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1b5aa1fd368..e87475c87d5 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -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); diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 5084595eb91..cf238bf5700 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -270,6 +270,10 @@ #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 diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 595ac638039..40553913b92 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -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); diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 4b9c3d6396f..a1367ab6f26 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -129,6 +129,10 @@ #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 @@ -142,6 +146,7 @@ #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 -- cgit v1.2.3-70-g09d2 From 790cfb34ad645be3bf69265cb05d824aeabcfa11 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Oct 2009 23:26:09 -0400 Subject: drm/radeon/kms: add quirk for acer 5102 doesn't have a tv-out port Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 8298c990be7..fcb9371bf05 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1579,6 +1579,17 @@ 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; + + return true; +} + bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; @@ -1896,16 +1907,18 @@ 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); + } } } } -- cgit v1.2.3-70-g09d2 From bc293e58cb4095f2ad43fe672ae269e31d1a18e2 Mon Sep 17 00:00:00 2001 From: Mathias Fröhlich Date: Mon, 19 Oct 2009 17:49:49 -0400 Subject: drm/radeon/kms/atom: get better min pixel clock info Where supported use ulMinPixelClockPLL_Output rather than usMinPixelClockPLL_Output for pll_out_min. This seems to improve pll selection on some boards. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 79d4b771c77..cec67917179 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -641,8 +641,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); -- cgit v1.2.3-70-g09d2 From c54b1820d69a1043acaf50d084852e628266e0e2 Mon Sep 17 00:00:00 2001 From: Robert Noland Date: Tue, 20 Oct 2009 08:11:36 -0500 Subject: drm/radeon/r600: Replace repeated calculations with variable. - Reduce the chance of error and avoid a bit of overhead. - Use switch to assign color and format Signed-off-by: Robert Noland Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_blit.c | 52 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c index d988eece018..626a9ab7075 100644 --- a/drivers/gpu/drm/radeon/r600_blit.c +++ b/drivers/gpu/drm/radeon/r600_blit.c @@ -774,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; @@ -790,16 +791,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); @@ -807,31 +802,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(dx + w); - vb[9] = i2f(dy + h); - vb[10] = i2f(sx + w); - vb[11] = i2f(sy + h); + vb[8] = i2f(dx2); + vb[9] = i2f(dy2); + vb[10] = i2f(sx2); + vb[11] = i2f(sy2); + + 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 + @@ -844,7 +854,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; } -- cgit v1.2.3-70-g09d2 From 33fdb15c99aac20d238af487fa363d3e5c7ed197 Mon Sep 17 00:00:00 2001 From: Robert Noland Date: Tue, 20 Oct 2009 13:07:38 -0500 Subject: drm/radeon/r600: only assign vb after we know space is available. This patch only changes this is the swap path, where it doesn't loop. Signed-off-by: Robert Noland Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_blit.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c index 626a9ab7075..5ea43234758 100644 --- a/drivers/gpu/drm/radeon/r600_blit.c +++ b/drivers/gpu/drm/radeon/r600_blit.c @@ -778,8 +778,6 @@ r600_blit_swap(struct drm_device *dev, u64 vb_addr; u32 *vb; - vb = r600_nomm_get_vb_ptr(dev); - if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { r600_nomm_put_vb(dev); @@ -788,8 +786,8 @@ r600_blit_swap(struct drm_device *dev, return; set_shaders(dev); - vb = r600_nomm_get_vb_ptr(dev); } + vb = r600_nomm_get_vb_ptr(dev); sx2 = sx + w; sy2 = sy + h; -- cgit v1.2.3-70-g09d2 From c290dadf4cac25cc91529d84004795ab43fc0821 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 22 Oct 2009 16:12:34 -0400 Subject: drm/radeon/kms/r7xx: add regs for 40 bit CUR/GRPH addresses The *_HIGH regs are reversed. The secondary ones are in the primary block and vice versa. We currently only use a 32 bit internal address, so these are 0 for now. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 10 ++++++++++ drivers/gpu/drm/radeon/r500_reg.h | 9 +++++++++ drivers/gpu/drm/radeon/radeon_cursor.c | 10 ++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f7dcb691683..9c26e538a1e 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -577,6 +577,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 + diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index 868add6e166..7baa7395556 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -384,9 +384,16 @@ # 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 @@ -404,6 +411,8 @@ # 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 diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index b13c79e38bc..28772a37009 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -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); -- cgit v1.2.3-70-g09d2 From ebbe1cb936dfc96d809ccf4d64a9755f8ba0c0ff Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Oct 2009 11:15:25 -0400 Subject: drm/radeon/kms/atom: add support for spread spectrum (v2) Spread spectrum is a periodic disturbance added to the feedback divider to change the pixel clock periodically to reduce interference. Only enabled on LVDS. v2: add support for r4xx and fix DCE 3 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios.h | 2 +- drivers/gpu/drm/radeon/atombios_crtc.c | 68 ++++++++++++++++++++++++++------ drivers/gpu/drm/radeon/radeon_atombios.c | 42 ++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_mode.h | 11 ++++++ 4 files changed, 111 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 5d402086bc4..c11ddddfb3b 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -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; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 9c26e538a1e..e5a3c301b7a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -351,6 +351,61 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, 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); + dig = radeon_encoder->enc_priv; + /* only enable spread spectrum on LVDS */ + 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; + break; + } + } + + if (!radeon_encoder) + return; + + if (ASIC_IS_AVIVO(rdev)) { + memset(&args, 0, sizeof(args)); + args.usSpreadSpectrumPercentage = 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 = 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) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); @@ -373,8 +428,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)) @@ -385,15 +438,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; @@ -641,7 +685,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, /* TODO color tiling */ + atombios_set_ss(crtc, 0); atombios_crtc_set_pll(crtc, adjusted_mode); + atombios_set_ss(crtc, 1); atombios_crtc_set_timing(crtc, adjusted_mode); if (ASIC_IS_AVIVO(rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index cec67917179..18729259c2f 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -771,6 +771,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; @@ -826,6 +866,8 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct /* 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; } return lvds; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index b6868fbe734..2ea5707c018 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -260,6 +260,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; @@ -267,6 +277,7 @@ struct radeon_encoder_atom_dig { /* atom lvds */ uint32_t lvds_misc; uint16_t panel_pwr_delay; + struct radeon_atom_ss *ss; /* panel mode */ struct drm_display_mode native_mode; }; -- cgit v1.2.3-70-g09d2 From 3e5cb98dfe87cc61d0a1119dd8aa2b1e4cfab424 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Oct 2009 12:21:24 -0400 Subject: drm/radeon/kms: add support for msi Try to enable msi on chips that support it. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 17 ++++++++++++++++- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_irq_kms.c | 9 +++++++++ drivers/gpu/drm/radeon/radeon_reg.h | 6 ++++++ drivers/gpu/drm/radeon/rs600.c | 18 +++++++++++++++++- 5 files changed, 49 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index ed5e983d21e..b438b520ee7 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -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; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8b60e36b20b..ea3efd7ae85 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -784,6 +784,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, diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 8e0a8759e42..a0fe6232dcb 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -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); } } diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index bfa1ab9c93e..29ab75903ec 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -290,6 +290,8 @@ #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) @@ -297,6 +299,9 @@ # 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 */ @@ -3311,6 +3316,7 @@ #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 diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 10dfa78762d..942754c39be 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -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; } -- cgit v1.2.3-70-g09d2 From 93239ea158368016a017200cb133e1057fb3ef89 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 28 Oct 2009 11:09:58 +1000 Subject: drm/radeon/kms: ignore vga arbiter return. Since we register all radeon devices, and the arbiter only cares about VGA class ones, we will fail to startup on display controller class devices. We don't gain anything by using the return value here. this helps kms on sparc64 get started. Reported-by: David S. Miller Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 3d667031de6..df988142e6b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -582,10 +582,9 @@ int radeon_device_init(struct radeon_device *rdev, DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); /* if we have > 1 VGA cards, then disable the radeon VGA resources */ - r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); - if (r) { - return -EINVAL; - } + /* this will fail for cards that aren't VGA class devices, just + * ignore it */ + vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); r = radeon_init(rdev); if (r) -- cgit v1.2.3-70-g09d2 From fcb45611448098a36b893bda71e72bd39730a3dd Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 14 Oct 2009 09:11:25 +0800 Subject: drm: Add the basic check for the detailed timing in EDID Sometimes we will get the incorrect display modeline when parsing the detailed timing in EDID. For example: >hsync/vsync width is zero >sync is beyond the blank. So add the basic check for the detailed timing in EDID to avoid the incorrect display modeline. Signed-off-by: Zhao Yakui Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3c0d2b3aed7..cea665d86dd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -626,6 +626,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; } + /* it is incorrect if hsync/vsync width is zero */ + if (!hsync_pulse_width || !vsync_pulse_width) { + DRM_DEBUG_KMS("Incorrect Detailed timing. " + "Wrong Hsync/Vsync pulse width\n"); + return NULL; + } mode = drm_mode_create(dev); if (!mode) return NULL; @@ -647,6 +653,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->vsync_end = mode->vsync_start + vsync_pulse_width; mode->vtotal = mode->vdisplay + vblank; + /* perform the basic check for the detailed timing */ + if (mode->hsync_end > mode->htotal || + mode->vsync_end > mode->vtotal) { + drm_mode_destroy(dev, mode); + DRM_DEBUG_KMS("Incorrect detailed timing. " + "Sync is beyond the blank.\n"); + return NULL; + } + drm_mode_set_name(mode); if (pt->misc & DRM_EDID_PT_INTERLACED) -- cgit v1.2.3-70-g09d2 From 77de0846aed9d7a1b0ea65090620900d66fb5cfb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 23 Oct 2009 18:49:03 +1000 Subject: drm/kms: fix kms/fbdev colormap support properly. This sets the fbcon to use TRUECOLOR by default, it then only modifies the pseudo palette for fbcon, and only touches the real palette when in 8-bit pseudo color mode. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 23dc9c115fd..9c924614c41 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -454,22 +454,39 @@ out_free: } EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); -static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, +static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; int pindex; + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *palette; + u32 value; + /* place color in psuedopalette */ + if (regno > 16) + return -EINVAL; + palette = (u32 *)info->pseudo_palette; + red >>= (16 - info->var.red.length); + green >>= (16 - info->var.green.length); + blue >>= (16 - info->var.blue.length); + value = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + palette[regno] = value; + return 0; + } + pindex = regno; if (fb->bits_per_pixel == 16) { pindex = regno << 3; if (fb->depth == 16 && regno > 63) - return; + return -EINVAL; if (fb->depth == 15 && regno > 31) - return; + return -EINVAL; if (fb->depth == 16) { u16 r, g, b; @@ -493,13 +510,7 @@ static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, if (fb->depth != 16) fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex); - - if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - ((u32 *) fb->pseudo_palette)[regno] = - (regno << info->var.red.offset) | - (regno << info->var.green.offset) | - (regno << info->var.blue.offset); - } + return 0; } int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) @@ -536,7 +547,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) if (transp) htransp = *transp++; - setcolreg(crtc, hred, hgreen, hblue, start++, info); + rc = setcolreg(crtc, hred, hgreen, hblue, start++, info); + if (rc) + return rc; } crtc_funcs->load_lut(crtc); } @@ -555,6 +568,7 @@ int drm_fb_helper_setcolreg(unsigned regno, struct drm_device *dev = fb_helper->dev; struct drm_crtc *crtc; int i; + int ret; if (regno > 255) return 1; @@ -568,8 +582,10 @@ int drm_fb_helper_setcolreg(unsigned regno, if (i == fb_helper->crtc_count) continue; + ret = setcolreg(crtc, red, green, blue, regno, info); + if (ret) + return ret; - setcolreg(crtc, red, green, blue, regno, info); crtc_funcs->load_lut(crtc); } return 0; @@ -928,7 +944,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, { info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : - FB_VISUAL_DIRECTCOLOR; + FB_VISUAL_TRUECOLOR; info->fix.type_aux = 0; info->fix.xpanstep = 1; /* doing it in hw */ info->fix.ypanstep = 1; /* doing it in hw */ -- cgit v1.2.3-70-g09d2 From 8f552a66a40bcc6e903e91310f42fe140e0342c4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 27 Oct 2009 11:16:09 -0400 Subject: drm/radeon/kms/atom: loosen pll min output limits 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. That's why the limits are in the bios tables. 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 or per clock range in the future. See fdo bug 24727. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 18729259c2f..1c9a9c46176 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -655,6 +655,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 = -- cgit v1.2.3-70-g09d2 From d56ef9c8fd34ed29ffae27598a864b4a9a82521b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 27 Oct 2009 12:11:09 -0400 Subject: drm/radeon/kms/atom: Fix DVO support DVO in 12 bit mode (which seems to be the most common config) requires 2x ppll. Fixes fdo bug 21857. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index e5a3c301b7a..8516e1b2329 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -483,8 +483,14 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) 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 - adjusted_clock = mode->clock; + } 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; -- cgit v1.2.3-70-g09d2 From 61c4b24b3e3bb83bfe29f24fe566281b4f722237 Mon Sep 17 00:00:00 2001 From: Mathias Fröhlich Date: Tue, 27 Oct 2009 15:08:01 -0400 Subject: drm/radeon/kms/atom: Make card_info per device Make the struct card_info, which is a per struct radeon_device dataset, a struct member of the radeon device instead of a static per kernel module value. This should avoid potential problems with two radeon cards installed in one system. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 29 +++++++++++++++++------------ drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index d1cdda9b558..88c19070247 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -443,20 +443,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; } @@ -464,6 +468,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) diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 2ea5707c018..ccb783868ad 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -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]; -- cgit v1.2.3-70-g09d2 From a2d49ae7df5b96fba3c63710df61412587fc6a24 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Tue, 27 Oct 2009 21:09:24 +0000 Subject: drm/kms: typo fix I believe this is a typo. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 9c924614c41..dc8e374a0b5 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -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; -- cgit v1.2.3-70-g09d2 From d11aa88b33b071d55181a7a482b9e7494888c10e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Oct 2009 00:51:20 -0400 Subject: drm/radeon/kms/atom: fix potential oops in spread spectrum code Make sure we have an LVDS encoder before casting enc_priv. [airlied: also fix two missing cpu_to_le16 casts we noticed on irc] Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 8516e1b2329..c15287a590f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -368,14 +368,17 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc == crtc) { radeon_encoder = to_radeon_encoder(encoder); - dig = radeon_encoder->enc_priv; /* only enable spread spectrum on LVDS */ - if (dig && dig->ss) { - percentage = dig->ss->percentage; - type = dig->ss->type; - step = dig->ss->step; - delay = dig->ss->delay; - range = dig->ss->range; + 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; @@ -387,7 +390,7 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) if (ASIC_IS_AVIVO(rdev)) { memset(&args, 0, sizeof(args)); - args.usSpreadSpectrumPercentage = percentage; + args.usSpreadSpectrumPercentage = cpu_to_le16(percentage); args.ucSpreadSpectrumType = type; args.ucSpreadSpectrumStep = step; args.ucSpreadSpectrumDelay = delay; @@ -397,7 +400,7 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } else { memset(&legacy_args, 0, sizeof(legacy_args)); - legacy_args.usSpreadSpectrumPercentage = percentage; + 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; -- cgit v1.2.3-70-g09d2 From fc7f7119d2ed97fff1aaddad6bf7d61ed446cf37 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 28 Oct 2009 01:46:54 -0400 Subject: drm/radeon/kms: add quirk for hp dc5750 Doesn't have a tv-out port Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index fcb9371bf05..a36ede002ee 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1587,6 +1587,12 @@ static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev) 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; } -- cgit v1.2.3-70-g09d2 From ea1495a6274c9542a168337536f8ce74d1173f23 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 27 Oct 2009 11:57:53 +1100 Subject: drm/radeon/kms: fix rc410 suspend/resume. This fixes suspend/resume on my rc410 motherboard, it restores the memory controller setup before posting the GPU, since it seems to need the MC_FB_LOCATION setup correctly. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rs400.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index a769c296f6a..ca037160a58 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -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", -- cgit v1.2.3-70-g09d2 From c9354c85c1c7bac788ce57d3c17f2016c1c45b1d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 2 Nov 2009 09:29:55 -0800 Subject: i915: fix intel graphics suspend breakage due to resume/lid event confusion In commit c1c7af60892070e4b82ad63bbfb95ae745056de0 ("drm/i915: force mode set at lid open time") the intel graphics driver was taught to restore the LVDS mode on lid open. That caused problems with interaction with the suspend/resume code, which commonly runs at the same time (suspend is often caused by the lid close event, while lid open is commonly a resume event), which was worked around with in commit 06891e27a9b5dba5268bb80e41a283f51335afe7 ("drm/i915: fix suspend/resume breakage in lid notifier"). However, in the meantime the lid event code had also grown a user event notifier (commit 06324194eee97a51b5f172270df49ec39192d6cc: "drm/i915: generate a KMS uevent at lid open/close time"), and now _that_ causes problems with suspend/resume and some versions of Xorg reacting to those uevents by setting the mode. So this effectively reverts that commit 06324194ee, and makes the lid open protection logic against suspend/resume more explicit. This fixes at least one laptop. See http://bugzilla.kernel.org/show_bug.cgi?id=14484 for more details. Acked-by: Jesse Barnes Cc: Riccardo Magliocchetti Cc: Eric Anholt Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_drv.c | 5 +++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 25 ++++++++++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b93814c0d3e..7f436ec075f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -89,7 +89,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) pci_set_power_state(dev->pdev, PCI_D3hot); } - dev_priv->suspended = 1; + /* Modeset on resume, not lid events */ + dev_priv->modeset_on_lid = 0; return 0; } @@ -124,7 +125,7 @@ static int i915_resume(struct drm_device *dev) drm_helper_resume_force_mode(dev); } - dev_priv->suspended = 0; + dev_priv->modeset_on_lid = 0; return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6035d3dae85..c5df2234418 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -274,7 +274,7 @@ typedef struct drm_i915_private { struct drm_i915_display_funcs display; /* Register state */ - bool suspended; + bool modeset_on_lid; u8 saveLBB; u32 saveDSPACNTR; u32 saveDSPBCNTR; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 98ae3d73577..808bbe412ba 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -656,6 +656,15 @@ static int intel_lvds_get_modes(struct drm_connector *connector) return 0; } +/* + * Lid events. Note the use of 'modeset_on_lid': + * - we set it on lid close, and reset it on open + * - we use it as a "only once" bit (ie we ignore + * duplicate events where it was already properly + * set/reset) + * - the suspend/resume paths will also set it to + * zero, since they restore the mode ("lid open"). + */ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, void *unused) { @@ -663,13 +672,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, container_of(nb, struct drm_i915_private, lid_notifier); struct drm_device *dev = dev_priv->dev; - if (acpi_lid_open() && !dev_priv->suspended) { - mutex_lock(&dev->mode_config.mutex); - drm_helper_resume_force_mode(dev); - mutex_unlock(&dev->mode_config.mutex); + if (!acpi_lid_open()) { + dev_priv->modeset_on_lid = 1; + return NOTIFY_OK; } - drm_sysfs_hotplug_event(dev_priv->dev); + if (!dev_priv->modeset_on_lid) + return NOTIFY_OK; + + dev_priv->modeset_on_lid = 0; + + mutex_lock(&dev->mode_config.mutex); + drm_helper_resume_force_mode(dev); + mutex_unlock(&dev->mode_config.mutex); return NOTIFY_OK; } -- cgit v1.2.3-70-g09d2 From df67bed92fa86ef926da8b62a6da68722388ff72 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 Oct 2009 13:31:26 +1000 Subject: drm/radeon/kms: fix coherency issues on AGP cards. When we are evicting from VRAM->RAM we allocate the ttm object, but we don't set the caching policy on it before blitting into it. This means on AGP we end up blitting into cached pages, and the CPU later flushes out on top of them. This was mostly seen as font corruption. The other question is why we don't evict VRAM->GTT in a lot of cases, this would save us some cache transitions since a lot of objects that are evicted from VRAM will probably end up being pulled back in a few operations later, and evicting them to system memory involves 2 unnecessary cache transitions. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_ttm.c | 6 ++++++ drivers/gpu/drm/ttm/ttm_tt.c | 1 + 2 files changed, 7 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index c729cd1a750..f489c0de6f1 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -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; diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index a55ee1a56c1..7bcb89f39ce 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -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) { -- cgit v1.2.3-70-g09d2 From d6f28938d9426d12eea1578949f1d73d24ad37ec Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Nov 2009 16:01:27 -0500 Subject: drm/radeon/kms: Don't RMW CP_RB_CNTL Immediate readback seems faulty on some chips. I suspect it takes a while to get through the fifo to the actual register backbone. There's no need to read it back, so, just write the driver's copy of the register's value directly. Should fix bug 24535 and possibly 24218 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 12 ++++++------ drivers/gpu/drm/radeon/r600.c | 8 +++----- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index b438b520ee7..5e821a313a8 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -578,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); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e87475c87d5..60fbb236edf 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1272,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(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz); -#else - WREG32(CP_RB_CNTL, RB_NO_UPDATE | (drm_order(RADEON_GPU_PAGE_SIZE/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); -- cgit v1.2.3-70-g09d2 From 8a9832e89ff1bc7a039c8f966f07101570be3d5e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Nov 2009 13:23:15 +1000 Subject: drm/radeon/kms: disable D1VGA and D2VGA if enabled Once kms is enabled we don't need these, and it causes a problem with the Lenovo W500 ACPI brightness implementation, it hangs in a loop inside an SMI. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rv515.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 41a34c23e6d..03c052d892c 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -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); } -- cgit v1.2.3-70-g09d2 From 4d357abb895ec51f1cbdebb1fbbf4d4576900a2e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Nov 2009 14:54:36 +1000 Subject: drm/radeon/kms: stop putting VRAM at 0 in MC space on r600s. The Lenovo W500 laptop hangs inside an SMI on brightness changes, I thought it just needed the VGA disable but it turned out to require slightly more work, setting the MC locations up just like the IGP chip requirements seems to make it all happy again and I can boot and play with brightness. We should probably just do this for all chips and give up the VRAM at 0x0 idea, it never seems to buy us anything but pain. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 44 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 60fbb236edf..3e5703f324b 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -409,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; -- cgit v1.2.3-70-g09d2 From 6fa8d66af83710b3610bd3b2581f051074f2b416 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 3 Nov 2009 16:10:36 -0500 Subject: drm/radeon/kms: remove some misleading debugging output Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_bios.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 34a9b911951..906921740c6 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -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); -- cgit v1.2.3-70-g09d2 From e29649db3bd5620499bf9bdcd63c5cf12edbd26e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 3 Nov 2009 10:04:01 -0500 Subject: drm/radeon/kms/r700: fix some typos in chip init Noticed by Andre on IRC. Also fix up some minor whitespace issues. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rv770.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 40553913b92..ae074fdf804 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -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); -- cgit v1.2.3-70-g09d2 From ba86bf8bfc1add5f515db8cf1d6042bb9396a299 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Oct 2009 16:29:16 +0000 Subject: drm/i915: Avoid potential sleep whilst holding spinlock Miles Lane reported the following error: 2 locks held by cat/4179: #0: (&p->lock){+.+.+.}, at: [] seq_read+0x25/0x315 #1: (&dev_priv->mm.active_list_lock){+.+...}, at: [] i915_batchbuffer_info+0x2b/0x124 Pid: 4179, comm: cat Not tainted 2.6.32-rc5-git1 #2 Call Trace: [] ? __debug_show_held_locks+0x1e/0x20 [] __might_sleep+0xf0/0xf7 [] kmap+0x17/0x58 [] i915_batchbuffer_info+0xad/0x124 [] seq_read+0x160/0x315 [] ? rw_verify_area+0x98/0xbb [] ? seq_read+0x0/0x315 [] vfs_read+0x75/0xa9 [] sys_read+0x3b/0x5d [] sysenter_do_call+0x12/0x36 The fix is relatively simple, use the atomic variants of kmap() that avoid the potential sleep. Signed-off-by: Chris Wilson Cc: Miles Lane Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f8ce9a3a420..26bf0552b3c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -267,10 +267,10 @@ static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_co uint32_t *mem; for (page = 0; page < page_count; page++) { - mem = kmap(pages[page]); + mem = kmap_atomic(pages[page], KM_USER0); for (i = 0; i < PAGE_SIZE; i += 4) seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); - kunmap(pages[page]); + kunmap_atomic(pages[page], KM_USER0); } } -- cgit v1.2.3-70-g09d2 From 4bfe6b6876a036d26a960320f1ab0bbd752c19bf Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 2 Nov 2009 07:52:29 +0000 Subject: drm/i915: Fix and cleanup DPLL calculation for Ironlake When the ideal error range can't be reached, this will safely use a most closed one. Clean up some dumb codes in DPLL function too. This fixes DPLL clock issue against one monitor at 1680x1050@60hz. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3ba6546b7c7..099f420de57 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -863,10 +863,8 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; intel_clock_t clock; - int max_n; - bool found; int err_most = 47; - found = false; + int err_min = 10000; /* eDP has only 2 clock choice, no n/m/p setting */ if (HAS_eDP) @@ -890,10 +888,9 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, } memset(best_clock, 0, sizeof(*best_clock)); - max_n = limit->n.max; for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { /* based on hardware requriment prefer smaller n to precision */ - for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) { + for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { /* based on hardware requirment prefere larger m1,m2 */ for (clock.m1 = limit->m1.max; clock.m1 >= limit->m1.min; clock.m1--) { @@ -907,18 +904,18 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, this_err = abs((10000 - (target*10000/clock.dot))); if (this_err < err_most) { *best_clock = clock; - err_most = this_err; - max_n = clock.n; - found = true; /* found on first matching */ goto out; + } else if (this_err < err_min) { + *best_clock = clock; + err_min = this_err; } } } } } out: - return found; + return true; } /* DisplayPort has only two frequencies, 162MHz and 270MHz */ -- cgit v1.2.3-70-g09d2 From d8a2d0e00c0d5a0d55e14b884bff034205015e51 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 2 Nov 2009 07:52:30 +0000 Subject: drm/i915: HDMI hardware workaround for Ironlake This brings some hardware workaround for HDMI port on PCH (Ibex Peak), which fixes unstable issues like during rotation. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_hdmi.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 663ab6de0b5..c33451aec1b 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -77,14 +77,32 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; u32 temp; - if (mode != DRM_MODE_DPMS_ON) { - temp = I915_READ(hdmi_priv->sdvox_reg); + temp = I915_READ(hdmi_priv->sdvox_reg); + + /* HW workaround, need to toggle enable bit off and on for 12bpc, but + * we do this anyway which shows more stable in testing. + */ + if (IS_IGDNG(dev)) { I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); + POSTING_READ(hdmi_priv->sdvox_reg); + } + + if (mode != DRM_MODE_DPMS_ON) { + temp &= ~SDVO_ENABLE; } else { - temp = I915_READ(hdmi_priv->sdvox_reg); - I915_WRITE(hdmi_priv->sdvox_reg, temp | SDVO_ENABLE); + temp |= SDVO_ENABLE; } + + I915_WRITE(hdmi_priv->sdvox_reg, temp); POSTING_READ(hdmi_priv->sdvox_reg); + + /* HW workaround, need to write this twice for issue that may result + * in first write getting masked. + */ + if (IS_IGDNG(dev)) { + I915_WRITE(hdmi_priv->sdvox_reg, temp); + POSTING_READ(hdmi_priv->sdvox_reg); + } } static void intel_hdmi_save(struct drm_connector *connector) -- cgit v1.2.3-70-g09d2 From ee59f2b462b0a7d2eb57ae59340d016589fa8e42 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 5 Nov 2009 13:11:46 -0500 Subject: drm/radeon/kms/r600: fix rs880 support v2 Lots of cases were wrong or missing. v2: rebased against drm-next Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 18 ++++++++++++------ drivers/gpu/drm/radeon/r600_blit_kms.c | 2 +- drivers/gpu/drm/radeon/radeon_atombios.c | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 3e5703f324b..35360b09df3 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -858,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); @@ -875,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) | @@ -918,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; @@ -975,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)); @@ -1001,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: @@ -1043,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: diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index acae33e2ad5..dbf716e1fbf 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -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 diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 1c9a9c46176..050722492b4 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -277,7 +277,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; -- cgit v1.2.3-70-g09d2 From 4170a6c1bc106d7fcf94f5842224ac4dac61006b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 5 Nov 2009 01:16:23 -0500 Subject: drm/radeon/kms/atom/dce3: fix up usPixelClock calculation for Transmitter tables Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 2aa5994a29d..355b0fbed92 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -725,10 +725,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) 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.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); args.v2.acConfig.fDualLinkConnector = 1; } else { - args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 4) / 100); + args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); } if (dig->dig_block) args.v2.acConfig.ucEncoderSel = 1; @@ -754,7 +754,10 @@ 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); + 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); switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: -- cgit v1.2.3-70-g09d2 From b75fad0682caacb16012582deecbd7d19bc2f68e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 5 Nov 2009 13:16:01 -0500 Subject: drm/radeon/kms: store detailed connector info This will be useful for mode validation and certain atom tables. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 76 +++++++++++++- drivers/gpu/drm/radeon/radeon_combios.c | 162 +++++++++++++++++++++-------- drivers/gpu/drm/radeon/radeon_connectors.c | 8 +- drivers/gpu/drm/radeon/radeon_mode.h | 1 + 4 files changed, 199 insertions(+), 48 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 050722492b4..80aacded85a 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -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; @@ -312,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 @@ -322,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) @@ -426,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); } } @@ -436,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; @@ -594,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); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index a36ede002ee..5253cbf6db1 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -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 @@ -1176,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); @@ -1188,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); @@ -1200,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); @@ -1218,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); @@ -1230,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) { @@ -1243,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: @@ -1257,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, @@ -1266,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, @@ -1275,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", @@ -1288,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, @@ -1301,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, @@ -1313,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", @@ -1326,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, @@ -1342,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, @@ -1351,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", @@ -1364,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, @@ -1373,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, @@ -1382,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", @@ -1399,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, @@ -1411,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", @@ -1431,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, @@ -1440,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", @@ -1453,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, @@ -1462,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, @@ -1471,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", @@ -1484,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, @@ -1493,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, @@ -1502,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", @@ -1596,11 +1627,46 @@ static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev) 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; @@ -1660,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) { @@ -1685,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; @@ -1714,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, @@ -1722,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), @@ -1742,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: @@ -1756,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", @@ -1788,7 +1864,8 @@ 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 { uint16_t crt_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); @@ -1804,7 +1881,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) 0, ATOM_DEVICE_CRT1_SUPPORT, DRM_MODE_CONNECTOR_VGA, - &ddc_i2c); + &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA); } else { DRM_DEBUG("No connector info found\n"); return false; @@ -1903,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); } } @@ -1923,7 +2002,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) radeon_add_legacy_connector(dev, 6, ATOM_DEVICE_TV1_SUPPORT, DRM_MODE_CONNECTOR_SVIDEO, - &ddc_i2c); + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO); } } } diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ce3a785a633..fb4d9184704 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -823,7 +823,8 @@ 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; @@ -862,6 +863,7 @@ 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); @@ -1013,7 +1015,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; @@ -1042,6 +1045,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); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index ccb783868ad..ace726aa0d7 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -317,6 +317,7 @@ struct radeon_connector { struct edid *edid; void *con_priv; bool dac_load_detect; + uint16_t connector_object_id; }; struct radeon_framebuffer { -- cgit v1.2.3-70-g09d2 From f95a9f0b05d22cffc46fbd2d065b260f8405e43f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 5 Nov 2009 02:21:06 -0500 Subject: drm/radeon/kms/atom/dce3: call transmitter init on mode set Generally this is done at post, but might not always be done with softboot or for connectors on docking stations. Could probably be done once when the driver loads/resumes rather than on each mode set. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 355b0fbed92..d42bc512d75 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -722,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) { + if (radeon_encoder->pixel_clock > 165000) args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); - args.v2.acConfig.fDualLinkConnector = 1; - } else { - args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); - } if (dig->dig_block) args.v2.acConfig.ucEncoderSel = 1; @@ -754,10 +757,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) } } else { args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; - 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); switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: @@ -1140,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; -- cgit v1.2.3-70-g09d2 From a3fa6320ce964f799388b152a1b0f6e2c3b32a7f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 5 Nov 2009 11:57:07 -0500 Subject: drm/radeon/kms: initial mode validation support Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 48 +++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index fb4d9184704..fce4c4087fd 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -397,6 +397,30 @@ 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; } @@ -512,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; } @@ -609,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; } @@ -801,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, }; -- cgit v1.2.3-70-g09d2 From 7433874e31f7f2e6e942b12012790565731d0f4a Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 3 Nov 2009 00:53:02 +0100 Subject: drm/radeon/kms: add debugfs for power management for AtomBIOS devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/Makefile | 2 +- drivers/gpu/drm/radeon/r420.c | 2 + drivers/gpu/drm/radeon/r520.c | 2 + drivers/gpu/drm/radeon/r600.c | 3 ++ drivers/gpu/drm/radeon/radeon.h | 8 ++++ drivers/gpu/drm/radeon/radeon_asic.h | 23 +++++++++++ drivers/gpu/drm/radeon/radeon_atombios.c | 18 +++++++++ drivers/gpu/drm/radeon/radeon_clocks.c | 2 +- drivers/gpu/drm/radeon/radeon_pm.c | 65 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/rs600.c | 2 + drivers/gpu/drm/radeon/rs690.c | 2 + drivers/gpu/drm/radeon/rv515.c | 2 + drivers/gpu/drm/radeon/rv770.c | 3 ++ 13 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/radeon/radeon_pm.c (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 09a28923f46..b5713eedd6e 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -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 diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 5c7fe52de30..1cefdbcc085 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -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) */ diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index a555b7b19b4..f7435185c0a 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -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) */ diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 35360b09df3..8d6bc12192d 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1621,10 +1621,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) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ea3efd7ae85..9f0bd984788 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -139,6 +139,10 @@ struct radeon_clock { uint32_t default_sclk; }; +/* + * Power management + */ +int radeon_pm_init(struct radeon_device *rdev); /* * Fences. @@ -622,7 +626,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); @@ -953,7 +959,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)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index d38f9963282..94991edc839 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -31,10 +31,13 @@ /* * 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); @@ -93,7 +96,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, @@ -145,7 +150,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, @@ -181,7 +188,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, @@ -222,7 +231,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, @@ -267,7 +278,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, @@ -305,7 +318,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, @@ -349,7 +364,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, @@ -384,7 +401,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, @@ -445,7 +464,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, @@ -481,7 +502,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, diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 80aacded85a..2ed88a82093 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1133,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) { diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index f5c32a766b1..a8135416762 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -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; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c new file mode 100644 index 00000000000..46146c6a2a0 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -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 + */ +#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 +} diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 942754c39be..5f117cd8736 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -488,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) */ diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 025e3225346..27547175cf9 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -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) */ diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 03c052d892c..7935f793bf6 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -587,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) */ diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index ae074fdf804..b0efd0ddae7 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -983,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) -- cgit v1.2.3-70-g09d2 From a39533b4ddad388b64a20bcabd17ac125fd4ba65 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 9 Nov 2009 16:41:21 -0500 Subject: drm/radeon/r600: CS parser updates Add some additional regs that require relocs. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_cs.c | 18 ++++++++++++++++++ drivers/gpu/drm/radeon/r600d.h | 10 ++++++++++ 2 files changed, 28 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 17e42195c63..0d820764f34 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -466,6 +466,23 @@ static int r600_packet3_check(struct radeon_cs_parser *p, for (i = 0; i < pkt->count; i++) { reg = start_reg + (4 * i); switch (reg) { + case SQ_ESGS_RING_BASE: + case SQ_GSVS_RING_BASE: + case SQ_ESTMP_RING_BASE: + case SQ_GSTMP_RING_BASE: + case SQ_VSTMP_RING_BASE: + case SQ_PSTMP_RING_BASE: + case SQ_FBUF_RING_BASE: + case SQ_REDUC_RING_BASE: + case SX_MEMORY_EXPORT_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad SET_CONFIG_REG " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case CP_COHER_BASE: /* use PACKET3_SURFACE_SYNC */ return -EINVAL; @@ -487,6 +504,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, reg = start_reg + (4 * i); switch (reg) { case DB_DEPTH_BASE: + case DB_HTILE_DATA_BASE: case CB_COLOR0_BASE: case CB_COLOR1_BASE: case CB_COLOR2_BASE: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index cf238bf5700..b99f45d85d8 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -118,6 +118,7 @@ #define DB_DEBUG 0x9830 #define PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31) #define DB_DEPTH_BASE 0x2800C +#define DB_HTILE_DATA_BASE 0x28014 #define DB_WATERMARKS 0x9838 #define DEPTH_FREE(x) ((x) << 0) #define DEPTH_FLUSH(x) ((x) << 5) @@ -170,6 +171,14 @@ #define SQ_STACK_RESOURCE_MGMT_2 0x8c14 # define NUM_GS_STACK_ENTRIES(x) ((x) << 0) # define NUM_ES_STACK_ENTRIES(x) ((x) << 16) +#define SQ_ESGS_RING_BASE 0x8c40 +#define SQ_GSVS_RING_BASE 0x8c48 +#define SQ_ESTMP_RING_BASE 0x8c50 +#define SQ_GSTMP_RING_BASE 0x8c58 +#define SQ_VSTMP_RING_BASE 0x8c60 +#define SQ_PSTMP_RING_BASE 0x8c68 +#define SQ_FBUF_RING_BASE 0x8c70 +#define SQ_REDUC_RING_BASE 0x8c78 #define GRBM_CNTL 0x8000 # define GRBM_READ_TIMEOUT(x) ((x) << 0) @@ -355,6 +364,7 @@ #define SX_MISC 0x28350 +#define SX_MEMORY_EXPORT_BASE 0x9010 #define SX_DEBUG_1 0x9054 #define SMX_EVENT_RELEASE (1 << 0) #define ENABLE_NEW_SMX_ADDRESS (1 << 16) -- cgit v1.2.3-70-g09d2 From eeba57518c01cf462d87bbfc59049139da47adcb Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 7 Nov 2009 16:27:32 +0100 Subject: drm/kms: Init the CRTC info fields for modes forced from the command line. Fixes fdo bug 24710. Signed-off-by: Francisco Jerez Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 1fe4e1d344f..bbfd110a716 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -331,6 +331,7 @@ create_mode: cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, cmdline_mode->rb, cmdline_mode->interlace, cmdline_mode->margins); + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); list_add(&mode->head, &connector->modes); return mode; } -- cgit v1.2.3-70-g09d2 From 2d109a845dd3074885db726892c629ab73dd0ed8 Mon Sep 17 00:00:00 2001 From: "Zou, Nanhai" Date: Fri, 6 Nov 2009 02:13:01 +0000 Subject: drm/i915: Fix IRQ stall issue on Ironlake The master irq control in DE must be disabled before irq handling, and enable after the process. This fixes the irq stall issue on Ironlake. Cc: Stable Team Signed-off-by: Zou, Nanhai Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_irq.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c3ceffa46ea..aa7fd82aa6e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -254,10 +254,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; - u32 de_iir, gt_iir; + u32 de_iir, gt_iir, de_ier; u32 new_de_iir, new_gt_iir; struct drm_i915_master_private *master_priv; + /* disable master interrupt before clearing iir */ + de_ier = I915_READ(DEIER); + I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); + (void)I915_READ(DEIER); + de_iir = I915_READ(DEIIR); gt_iir = I915_READ(GTIIR); @@ -290,6 +295,9 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) gt_iir = new_gt_iir; } + I915_WRITE(DEIER, de_ier); + (void)I915_READ(DEIER); + return ret; } -- cgit v1.2.3-70-g09d2 From 5586c8bc93ac5fe75f5fd14e8c7add5344d1c548 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 6 Nov 2009 02:13:02 +0000 Subject: drm/i915: Add more registers save/restore for Ironlake suspend Add more display registers save/restore to fix unstable issues during S4 testing on Ironlake. And DPLL_B_MD should not be restored on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++++ drivers/gpu/drm/i915/i915_suspend.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 57204e29897..a725f659119 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -296,6 +296,7 @@ typedef struct drm_i915_private { u32 saveVBLANK_A; u32 saveVSYNC_A; u32 saveBCLRPAT_A; + u32 saveTRANSACONF; u32 saveTRANS_HTOTAL_A; u32 saveTRANS_HBLANK_A; u32 saveTRANS_HSYNC_A; @@ -326,6 +327,7 @@ typedef struct drm_i915_private { u32 saveVBLANK_B; u32 saveVSYNC_B; u32 saveBCLRPAT_B; + u32 saveTRANSBCONF; u32 saveTRANS_HTOTAL_B; u32 saveTRANS_HBLANK_B; u32 saveTRANS_HSYNC_B; @@ -414,6 +416,16 @@ typedef struct drm_i915_private { u32 savePFB_WIN_SZ; u32 savePFA_WIN_POS; u32 savePFB_WIN_POS; + u32 savePCH_DREF_CONTROL; + u32 saveDISP_ARB_CTL; + u32 savePIPEA_DATA_M1; + u32 savePIPEA_DATA_N1; + u32 savePIPEA_LINK_M1; + u32 savePIPEA_LINK_N1; + u32 savePIPEB_DATA_M1; + u32 savePIPEB_DATA_N1; + u32 savePIPEB_LINK_M1; + u32 savePIPEB_LINK_N1; struct { struct drm_mm gtt_space; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 992d5617e79..6eec8171a44 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -239,6 +239,11 @@ static void i915_save_modeset_reg(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) return; + if (IS_IGDNG(dev)) { + dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); + dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); + } + /* Pipe & plane A info */ dev_priv->savePIPEACONF = I915_READ(PIPEACONF); dev_priv->savePIPEASRC = I915_READ(PIPEASRC); @@ -263,6 +268,11 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); if (IS_IGDNG(dev)) { + dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1); + dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1); + dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1); + dev_priv->savePIPEA_LINK_N1 = I915_READ(PIPEA_LINK_N1); + dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL); dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL); @@ -270,6 +280,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ); dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS); + dev_priv->saveTRANSACONF = I915_READ(TRANSACONF); dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A); dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A); dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A); @@ -314,6 +325,11 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B); if (IS_IGDNG(dev)) { + dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1); + dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1); + dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1); + dev_priv->savePIPEB_LINK_N1 = I915_READ(PIPEB_LINK_N1); + dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL); dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL); @@ -321,6 +337,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ); dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS); + dev_priv->saveTRANSBCONF = I915_READ(TRANSBCONF); dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B); dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B); dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B); @@ -368,6 +385,11 @@ static void i915_restore_modeset_reg(struct drm_device *dev) fpb1_reg = FPB1; } + if (IS_IGDNG(dev)) { + I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL); + I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL); + } + /* Pipe & plane A info */ /* Prime the clock */ if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { @@ -395,6 +417,11 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); if (IS_IGDNG(dev)) { + I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1); + I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1); + I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1); + I915_WRITE(PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1); + I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL); I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL); @@ -402,6 +429,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ); I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS); + I915_WRITE(TRANSACONF, dev_priv->saveTRANSACONF); I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A); I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A); I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A); @@ -439,7 +467,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) /* Actually enable it */ I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); DRM_UDELAY(150); - if (IS_I965G(dev)) + if (IS_I965G(dev) && !IS_IGDNG(dev)) I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); DRM_UDELAY(150); @@ -454,6 +482,11 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); if (IS_IGDNG(dev)) { + I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1); + I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1); + I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1); + I915_WRITE(PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1); + I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL); I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL); @@ -461,6 +494,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ); I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS); + I915_WRITE(TRANSBCONF, dev_priv->saveTRANSBCONF); I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B); I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B); I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B); -- cgit v1.2.3-70-g09d2 From 0592e4c49e5af8ef71a1aa9308a100d711c64911 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 16 Oct 2009 15:12:13 -0700 Subject: drm: radeon: Mark several functions static in mkregtable Signed-off-by: Josh Triplett --- drivers/gpu/drm/radeon/mkregtable.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/mkregtable.c b/drivers/gpu/drm/radeon/mkregtable.c index fb211e585de..0d79577c157 100644 --- a/drivers/gpu/drm/radeon/mkregtable.c +++ b/drivers/gpu/drm/radeon/mkregtable.c @@ -561,7 +561,7 @@ struct table { char *gpu_prefix; }; -struct offset *offset_new(unsigned o) +static struct offset *offset_new(unsigned o) { struct offset *offset; @@ -573,12 +573,12 @@ struct offset *offset_new(unsigned o) return offset; } -void table_offset_add(struct table *t, struct offset *offset) +static void table_offset_add(struct table *t, struct offset *offset) { list_add_tail(&offset->list, &t->offsets); } -void table_init(struct table *t) +static void table_init(struct table *t) { INIT_LIST_HEAD(&t->offsets); t->offset_max = 0; @@ -586,7 +586,7 @@ void table_init(struct table *t) t->table = NULL; } -void table_print(struct table *t) +static void table_print(struct table *t) { unsigned nlloop, i, j, n, c, id; @@ -611,7 +611,7 @@ void table_print(struct table *t) printf("};\n"); } -int table_build(struct table *t) +static int table_build(struct table *t) { struct offset *offset; unsigned i, m; @@ -631,7 +631,7 @@ int table_build(struct table *t) } static char gpu_name[10]; -int parser_auth(struct table *t, const char *filename) +static int parser_auth(struct table *t, const char *filename) { FILE *file; regex_t mask_rex; -- cgit v1.2.3-70-g09d2 From 0ebf17174b4bdd99ab81c476714c91ee335fdcbf Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Nov 2009 15:39:10 +1000 Subject: drm/radeon/kms: resume AGP by calling init. AGP resume was broken since we moved to the new init path, because we never re-enabled AGP on these systems at resume time. This patch just calls the AGP resume call which just does the reinit at resume time like the old path did. Since AGP is pretty much gpu independant I did it outside the gpu specific code. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_agp.c | 12 ++++++++++++ drivers/gpu/drm/radeon/radeon_device.c | 2 ++ 3 files changed, 15 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 757f5cd3774..224506a2f7b 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -519,6 +519,7 @@ typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p, * AGP */ int radeon_agp_init(struct radeon_device *rdev); +void radeon_agp_resume(struct radeon_device *rdev); void radeon_agp_fini(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 23ea9955ac5..54bf49a6d67 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -237,6 +237,18 @@ int radeon_agp_init(struct radeon_device *rdev) #endif } +void radeon_agp_resume(struct radeon_device *rdev) +{ +#if __OS_HAS_AGP + int r; + if (rdev->flags & RADEON_IS_AGP) { + r = radeon_agp_init(rdev); + if (r) + dev_warn(rdev->dev, "radeon AGP reinit failed\n"); + } +#endif +} + void radeon_agp_fini(struct radeon_device *rdev) { #if __OS_HAS_AGP diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e3f9edfa40f..41bb76fbe73 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -688,6 +688,8 @@ int radeon_resume_kms(struct drm_device *dev) return -1; } pci_set_master(dev->pdev); + /* resume AGP if in use */ + radeon_agp_resume(rdev); radeon_resume(rdev); radeon_restore_bios_scratch_regs(rdev); fb_set_suspend(rdev->fbdev_info, 0); -- cgit v1.2.3-70-g09d2 From 7064fef56369c9e2c6e35ff6d6b4b63d42a859ce Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 5 Nov 2009 10:12:54 -0800 Subject: drm: work around EDIDs with bad htotal/vtotal values We did this on the userspace side, but we need a similar fix for the kernel. Fixes LP #460664. Signed-off-by: Jesse Barnes Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index cea665d86dd..b54ba63d506 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -662,6 +662,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; } + /* Some EDIDs have bogus h/vtotal values */ + if (mode->hsync_end > mode->htotal) + mode->htotal = mode->hsync_end + 1; + if (mode->vsync_end > mode->vtotal) + mode->vtotal = mode->vsync_end + 1; + drm_mode_set_name(mode); if (pt->misc & DRM_EDID_PT_INTERLACED) -- cgit v1.2.3-70-g09d2 From ef63062716415d6e271815872b6c6654ffa9ac26 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Nov 2009 09:37:39 +1000 Subject: drm/radeon/kms: fix handling of d1/d2 vga An rv515 laptop I got wouldn't startup with a montior plugged in, found the proper bug hopefully with us not turning off D2VGA here when we should. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rv515.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 7935f793bf6..ba68c9fe90a 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -137,8 +137,6 @@ 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); } @@ -382,7 +380,6 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); /* Stop all video */ - WREG32(R_000330_D1VGA_CONTROL, 0); WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); WREG32(R_000300_VGA_RENDER_CONTROL, 0); WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); @@ -391,6 +388,8 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) WREG32(R_006880_D2CRTC_CONTROL, 0); WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); + WREG32(R_000330_D1VGA_CONTROL, 0); + WREG32(R_000338_D2VGA_CONTROL, 0); } void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) @@ -404,14 +403,14 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); /* Restore video state */ + WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); + WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); - WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); - WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); } -- cgit v1.2.3-70-g09d2 From 23115b0592bde5da249fcbdad7714c1f96a8e5f5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Nov 2009 15:53:44 +1000 Subject: drm/radeon/kms: read back register before writing in IIO. This fixes RH bugzilla #527874. On resume the atom posting wasn't working, however vbe posting was going fine, after 2 weeks over irc, and 8 hrs with the hardware, I tracked it down to the memory device table and it access the MC registers via IIO, it appears the rv515 atom iio table might not be fully functional, so adding a readback before doing a write either provides enough delay to make things resume correctly. Thanks to Peng Huang at Red Hat for coming to Brisbane. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 901befe03da..d67c42555ab 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -107,6 +107,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, base += 3; break; case ATOM_IIO_WRITE: + (void)ctx->card->reg_read(ctx->card, CU16(base + 1)); ctx->card->reg_write(ctx->card, CU16(base + 1), temp); base += 3; break; -- cgit v1.2.3-70-g09d2 From 0beb81ab45c67de4b3aa85faad604cff8ed133a8 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 13 Nov 2009 20:56:35 +0100 Subject: drm/radeon/kms: Disable TV load detect on RS400,RC410,RS480 RS400,RC410,RS480 chipset seems to report a lot of false positive with load detect on TV output. We haven't yet found a way to make load detect reliable on those chipset, thus just disable it for TV output. Would avoid user to experience phantom screen because X believe there is a monitor connected to the TV output. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index fce4c4087fd..55fecfc1f19 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1149,6 +1149,13 @@ radeon_add_legacy_connector(struct drm_device *dev, if (ret) goto failed; radeon_connector->dac_load_detect = true; + /* RS400,RC410,RS480 chipset seems to report a lot + * of false positive on load detect, we haven't yet + * found a way to make load detect reliable on those + * chipset, thus just disable it for TV. + */ + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) + radeon_connector->dac_load_detect = false; drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.load_detect_property, 1); -- cgit v1.2.3-70-g09d2 From a698cf34ea867efef12fc29dd63d443f0c71a53c Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 13 Nov 2009 20:56:58 +0100 Subject: drm: mm always protect change to unused_nodes with unused_lock spinlock unused_nodes modification needs to be protected by unused_lock spinlock. Here is an example of an usage where there is no such protection without this patch. Process 1: 1-drm_mm_pre_get(this function modify unused_nodes list) 2-spin_lock(spinlock protecting mm struct) 3-drm_mm_put_block(this function might modify unused_nodes list but doesn't protect modification with unused_lock) 4-spin_unlock(spinlock protecting mm struct) Process2: 1-drm_mm_pre_get(this function modify unused_nodes list) At this point Process1 & Process2 might both be doing modification to unused_nodes list. This patch add unused_lock protection into drm_mm_put_block to avoid such issue. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_mm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index c861d80fd77..97dc5a4f0de 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -103,6 +103,11 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic) return child; } +/* drm_mm_pre_get() - pre allocate drm_mm_node structure + * drm_mm: memory manager struct we are pre-allocating for + * + * Returns 0 on success or -ENOMEM if allocation fails. + */ int drm_mm_pre_get(struct drm_mm *mm) { struct drm_mm_node *node; @@ -253,12 +258,14 @@ void drm_mm_put_block(struct drm_mm_node *cur) prev_node->size += next_node->size; list_del(&next_node->ml_entry); list_del(&next_node->fl_entry); + spin_lock(&mm->unused_lock); if (mm->num_unused < MM_UNUSED_TARGET) { list_add(&next_node->fl_entry, &mm->unused_nodes); ++mm->num_unused; } else kfree(next_node); + spin_unlock(&mm->unused_lock); } else { next_node->size += cur->size; next_node->start = cur->start; @@ -271,11 +278,13 @@ void drm_mm_put_block(struct drm_mm_node *cur) list_add(&cur->fl_entry, &mm->fl_entry); } else { list_del(&cur->ml_entry); + spin_lock(&mm->unused_lock); if (mm->num_unused < MM_UNUSED_TARGET) { list_add(&cur->fl_entry, &mm->unused_nodes); ++mm->num_unused; } else kfree(cur); + spin_unlock(&mm->unused_lock); } } -- cgit v1.2.3-70-g09d2 From f82f5f3ac4de6c6b872fcbb3dec97f368e78ff58 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 12 Nov 2009 14:13:53 +0100 Subject: drm/radeon/kms: Report vga connector is connected according to ddc_probe On broken EDID we were reporting vga connector to be disconnected even if ddc probe did found a monitor. This patch report that the connector is connected on such case. This allow drm to add a fail safe mode (800x600 at the time of this patch) thus user can boot and later add a mode which match its monitor capabilities. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 55fecfc1f19..29763ceae3a 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -566,8 +566,9 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect 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)); + DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", + drm_get_connector_name(connector)); + ret = connector_status_connected; } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -720,8 +721,8 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect 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)); + DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", + drm_get_connector_name(connector)); } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); -- cgit v1.2.3-70-g09d2 From 79cc304f3e2fda202242036326afb2aeca486156 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 17 Nov 2009 14:08:54 -0800 Subject: drm: make sure page protections are updated after changing vm_flags Some architectures compute ->vm_page_prot depending on ->vm_flags, so we need to update the protections after adjusting the flags. AFAIK this only affects running X under Xen; without this patch you get lots of coloured blobs on the screen, or maybe a complete lockup. Or anything really. But that still depends on lots of out-of-tree stuff, so I don't think there are any consequences for anyone else. But it is wrong in principle. Reported-by: Jan Beulich Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 80391995bde..e9dbb481c46 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -552,7 +552,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; vma->vm_ops = obj->dev->driver->gem_vm_ops; vma->vm_private_data = map->handle; - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); /* Take a ref for this mapping of the object, so that the fault * handler can dereference the mmap offset's pointer to the object. -- cgit v1.2.3-70-g09d2 From 5349ef3127c77075ff70b2014f17ae0fbcaaf199 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 4 Nov 2009 09:42:52 +0100 Subject: drm/fb: fix FBIOGET/PUT_VSCREENINFO pixel clock handling When the framebuffer driver does not publish detailed timing information for the current video mode, the correct value for the pixclock field is zero, not -1. Since pixclock is actually unsigned, the value -1 would be interpreted as 4294967295 picoseconds (i.e., about 4 milliseconds) by register_framebuffer() and userspace programs. This patch allows X.org's fbdev driver to work. Signed-off-by: Clemens Ladisch Tested-by: Paulius Zaleckas Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index dc8e374a0b5..65ef011fa8b 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -599,7 +599,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct drm_framebuffer *fb = fb_helper->fb; int depth; - if (var->pixclock == -1 || !var->pixclock) + if (var->pixclock != 0) return -EINVAL; /* Need to resize the fb object !!! */ @@ -691,7 +691,7 @@ int drm_fb_helper_set_par(struct fb_info *info) int ret; int i; - if (var->pixclock != -1) { + if (var->pixclock != 0) { DRM_ERROR("PIXEL CLCOK SET\n"); return -EINVAL; } @@ -904,7 +904,7 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, fb_helper->fb = fb; if (new_fb) { - info->var.pixclock = -1; + info->var.pixclock = 0; if (register_framebuffer(info) < 0) return -EINVAL; } else { -- cgit v1.2.3-70-g09d2 From 8e9e0eea9955bffbe5e5cd6355157cabddc31f17 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 11 Nov 2009 02:30:50 +0000 Subject: drm/i915: Fix CRT hotplug detect by checking really no channels attached For CRT hotplug detect status, we have four test results as blue channel only, green channel only, both blue and green channel, and no channel attached. Origin code only marks both blue and green channel case as connected, but ignore other possible connected states. This one trys to detect CRT by checking no channel attached case instead. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_crt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 212e22740fc..e5051446c48 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -262,8 +262,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) } while (time_after(timeout, jiffies)); } - if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) == - CRT_HOTPLUG_MONITOR_COLOR) + if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != + CRT_HOTPLUG_MONITOR_NONE) return true; return false; -- cgit v1.2.3-70-g09d2 From ca9ab10033d190c1ede85fdf456307bdfdabf079 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Nov 2009 15:40:31 +0000 Subject: drm/i915: Select CONFIG_SHMEM The driver requires shmfs as the backing filesystem to handle the buffer objects, so ensure it is selected if the user chooses to build our driver. Fixes: Bug 14662 - Dell E5500 kernel panic with KMS http://bugzilla.kernel.org/show_bug.cgi?id=14662 The revealing nature of the panic is the NULL function pointer dereference in read_cache_page_async(). Signed-off-by: Chris Wilson Reported-and-tested-by: Mateusz Kaduk Signed-off-by: Eric Anholt Cc: stable@kernel.org --- drivers/gpu/drm/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index f831ea15929..96eddd17e05 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -92,6 +92,7 @@ config DRM_I830 config DRM_I915 tristate "i915 driver" depends on AGP_INTEL + select SHMEM select DRM_KMS_HELPER select FB_CFB_FILLRECT select FB_CFB_COPYAREA -- cgit v1.2.3-70-g09d2