| From e8321eb5f0641cd1b9d875b4c6c9dba063974c28 Mon Sep 17 00:00:00 2001 |
| From: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> |
| Date: Thu, 7 Nov 2013 00:14:18 +0100 |
| Subject: drm/gma500/mrst: Add aux register writes when programming pipe |
| |
| On SDVO pipes (always Pipe B on mrst) we have to sequentially write the |
| aux vdc. We might be able to skip programming the primary vdc in |
| some/most places but we don't care about that now. |
| |
| Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> |
| (cherry picked from commit b97b8287a39d1fe6f8aa1b83405f669634ff8401) |
| Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> |
| --- |
| drivers/gpu/drm/gma500/oaktrail_crtc.c | 247 ++++++++++++++++++--------------- |
| drivers/gpu/drm/gma500/psb_drv.h | 27 +++ |
| 2 files changed, 165 insertions(+), 109 deletions(-) |
| |
| --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c |
| +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c |
| @@ -227,6 +227,8 @@ static void oaktrail_crtc_dpms(struct dr |
| int pipe = gma_crtc->pipe; |
| const struct psb_offset *map = &dev_priv->regmap[pipe]; |
| u32 temp; |
| + int i; |
| + int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; |
| |
| if (pipe == 1) { |
| oaktrail_crtc_hdmi_dpms(crtc, mode); |
| @@ -243,35 +245,45 @@ static void oaktrail_crtc_dpms(struct dr |
| case DRM_MODE_DPMS_ON: |
| case DRM_MODE_DPMS_STANDBY: |
| case DRM_MODE_DPMS_SUSPEND: |
| - /* Enable the DPLL */ |
| - temp = REG_READ(map->dpll); |
| - if ((temp & DPLL_VCO_ENABLE) == 0) { |
| - REG_WRITE(map->dpll, temp); |
| - REG_READ(map->dpll); |
| - /* Wait for the clocks to stabilize. */ |
| - udelay(150); |
| - REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE); |
| - REG_READ(map->dpll); |
| - /* Wait for the clocks to stabilize. */ |
| - udelay(150); |
| - REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE); |
| - REG_READ(map->dpll); |
| - /* Wait for the clocks to stabilize. */ |
| - udelay(150); |
| - } |
| - /* Enable the pipe */ |
| - temp = REG_READ(map->conf); |
| - if ((temp & PIPEACONF_ENABLE) == 0) |
| - REG_WRITE(map->conf, temp | PIPEACONF_ENABLE); |
| - /* Enable the plane */ |
| - temp = REG_READ(map->cntr); |
| - if ((temp & DISPLAY_PLANE_ENABLE) == 0) { |
| - REG_WRITE(map->cntr, |
| - temp | DISPLAY_PLANE_ENABLE); |
| - /* Flush the plane changes */ |
| - REG_WRITE(map->base, REG_READ(map->base)); |
| - } |
| + for (i = 0; i <= need_aux; i++) { |
| + /* Enable the DPLL */ |
| + temp = REG_READ_WITH_AUX(map->dpll, i); |
| + if ((temp & DPLL_VCO_ENABLE) == 0) { |
| + REG_WRITE_WITH_AUX(map->dpll, temp, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + /* Wait for the clocks to stabilize. */ |
| + udelay(150); |
| + REG_WRITE_WITH_AUX(map->dpll, |
| + temp | DPLL_VCO_ENABLE, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + /* Wait for the clocks to stabilize. */ |
| + udelay(150); |
| + REG_WRITE_WITH_AUX(map->dpll, |
| + temp | DPLL_VCO_ENABLE, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + /* Wait for the clocks to stabilize. */ |
| + udelay(150); |
| + } |
| + |
| + /* Enable the pipe */ |
| + temp = REG_READ_WITH_AUX(map->conf, i); |
| + if ((temp & PIPEACONF_ENABLE) == 0) { |
| + REG_WRITE_WITH_AUX(map->conf, |
| + temp | PIPEACONF_ENABLE, i); |
| + } |
| + |
| + /* Enable the plane */ |
| + temp = REG_READ_WITH_AUX(map->cntr, i); |
| + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { |
| + REG_WRITE_WITH_AUX(map->cntr, |
| + temp | DISPLAY_PLANE_ENABLE, |
| + i); |
| + /* Flush the plane changes */ |
| + REG_WRITE_WITH_AUX(map->base, |
| + REG_READ_WITH_AUX(map->base, i), i); |
| + } |
| |
| + } |
| gma_crtc_load_lut(crtc); |
| |
| /* Give the overlay scaler a chance to enable |
| @@ -283,35 +295,40 @@ static void oaktrail_crtc_dpms(struct dr |
| * if it's on this pipe */ |
| /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ |
| |
| - /* Disable the VGA plane that we never use */ |
| - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); |
| - /* Disable display plane */ |
| - temp = REG_READ(map->cntr); |
| - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { |
| - REG_WRITE(map->cntr, |
| - temp & ~DISPLAY_PLANE_ENABLE); |
| - /* Flush the plane changes */ |
| - REG_WRITE(map->base, REG_READ(map->base)); |
| - REG_READ(map->base); |
| - } |
| + for (i = 0; i <= need_aux; i++) { |
| + /* Disable the VGA plane that we never use */ |
| + REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i); |
| + /* Disable display plane */ |
| + temp = REG_READ_WITH_AUX(map->cntr, i); |
| + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { |
| + REG_WRITE_WITH_AUX(map->cntr, |
| + temp & ~DISPLAY_PLANE_ENABLE, i); |
| + /* Flush the plane changes */ |
| + REG_WRITE_WITH_AUX(map->base, |
| + REG_READ(map->base), i); |
| + REG_READ_WITH_AUX(map->base, i); |
| + } |
| + |
| + /* Next, disable display pipes */ |
| + temp = REG_READ_WITH_AUX(map->conf, i); |
| + if ((temp & PIPEACONF_ENABLE) != 0) { |
| + REG_WRITE_WITH_AUX(map->conf, |
| + temp & ~PIPEACONF_ENABLE, i); |
| + REG_READ_WITH_AUX(map->conf, i); |
| + } |
| + /* Wait for for the pipe disable to take effect. */ |
| + gma_wait_for_vblank(dev); |
| + |
| + temp = REG_READ_WITH_AUX(map->dpll, i); |
| + if ((temp & DPLL_VCO_ENABLE) != 0) { |
| + REG_WRITE_WITH_AUX(map->dpll, |
| + temp & ~DPLL_VCO_ENABLE, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + } |
| |
| - /* Next, disable display pipes */ |
| - temp = REG_READ(map->conf); |
| - if ((temp & PIPEACONF_ENABLE) != 0) { |
| - REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE); |
| - REG_READ(map->conf); |
| - } |
| - /* Wait for for the pipe disable to take effect. */ |
| - gma_wait_for_vblank(dev); |
| - |
| - temp = REG_READ(map->dpll); |
| - if ((temp & DPLL_VCO_ENABLE) != 0) { |
| - REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE); |
| - REG_READ(map->dpll); |
| + /* Wait for the clocks to turn off. */ |
| + udelay(150); |
| } |
| - |
| - /* Wait for the clocks to turn off. */ |
| - udelay(150); |
| break; |
| } |
| |
| @@ -367,6 +384,8 @@ static int oaktrail_crtc_mode_set(struct |
| struct gma_encoder *gma_encoder = NULL; |
| uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; |
| struct drm_connector *connector; |
| + int i; |
| + int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; |
| |
| if (pipe == 1) |
| return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb); |
| @@ -401,15 +420,17 @@ static int oaktrail_crtc_mode_set(struct |
| } |
| |
| /* Disable the VGA plane that we never use */ |
| - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); |
| + for (i = 0; i <= need_aux; i++) |
| + REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i); |
| |
| /* Disable the panel fitter if it was on our pipe */ |
| if (oaktrail_panel_fitter_pipe(dev) == pipe) |
| REG_WRITE(PFIT_CONTROL, 0); |
| |
| - REG_WRITE(map->src, |
| - ((mode->crtc_hdisplay - 1) << 16) | |
| - (mode->crtc_vdisplay - 1)); |
| + for (i = 0; i <= need_aux; i++) { |
| + REG_WRITE_WITH_AUX(map->src, ((mode->crtc_hdisplay - 1) << 16) | |
| + (mode->crtc_vdisplay - 1), i); |
| + } |
| |
| if (gma_encoder) |
| drm_object_property_get_value(&connector->base, |
| @@ -426,35 +447,39 @@ static int oaktrail_crtc_mode_set(struct |
| offsetY = (adjusted_mode->crtc_vdisplay - |
| mode->crtc_vdisplay) / 2; |
| |
| - REG_WRITE(map->htotal, (mode->crtc_hdisplay - 1) | |
| - ((adjusted_mode->crtc_htotal - 1) << 16)); |
| - REG_WRITE(map->vtotal, (mode->crtc_vdisplay - 1) | |
| - ((adjusted_mode->crtc_vtotal - 1) << 16)); |
| - REG_WRITE(map->hblank, |
| - (adjusted_mode->crtc_hblank_start - offsetX - 1) | |
| - ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); |
| - REG_WRITE(map->hsync, |
| - (adjusted_mode->crtc_hsync_start - offsetX - 1) | |
| - ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); |
| - REG_WRITE(map->vblank, |
| - (adjusted_mode->crtc_vblank_start - offsetY - 1) | |
| - ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); |
| - REG_WRITE(map->vsync, |
| - (adjusted_mode->crtc_vsync_start - offsetY - 1) | |
| - ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); |
| + for (i = 0; i <= need_aux; i++) { |
| + REG_WRITE_WITH_AUX(map->htotal, (mode->crtc_hdisplay - 1) | |
| + ((adjusted_mode->crtc_htotal - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->vtotal, (mode->crtc_vdisplay - 1) | |
| + ((adjusted_mode->crtc_vtotal - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->hblank, |
| + (adjusted_mode->crtc_hblank_start - offsetX - 1) | |
| + ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->hsync, |
| + (adjusted_mode->crtc_hsync_start - offsetX - 1) | |
| + ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->vblank, |
| + (adjusted_mode->crtc_vblank_start - offsetY - 1) | |
| + ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->vsync, |
| + (adjusted_mode->crtc_vsync_start - offsetY - 1) | |
| + ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16), i); |
| + } |
| } else { |
| - REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) | |
| - ((adjusted_mode->crtc_htotal - 1) << 16)); |
| - REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) | |
| - ((adjusted_mode->crtc_vtotal - 1) << 16)); |
| - REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) | |
| - ((adjusted_mode->crtc_hblank_end - 1) << 16)); |
| - REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) | |
| - ((adjusted_mode->crtc_hsync_end - 1) << 16)); |
| - REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) | |
| - ((adjusted_mode->crtc_vblank_end - 1) << 16)); |
| - REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) | |
| - ((adjusted_mode->crtc_vsync_end - 1) << 16)); |
| + for (i = 0; i <= need_aux; i++) { |
| + REG_WRITE_WITH_AUX(map->htotal, (adjusted_mode->crtc_hdisplay - 1) | |
| + ((adjusted_mode->crtc_htotal - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) | |
| + ((adjusted_mode->crtc_vtotal - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->hblank, (adjusted_mode->crtc_hblank_start - 1) | |
| + ((adjusted_mode->crtc_hblank_end - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->hsync, (adjusted_mode->crtc_hsync_start - 1) | |
| + ((adjusted_mode->crtc_hsync_end - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->vblank, (adjusted_mode->crtc_vblank_start - 1) | |
| + ((adjusted_mode->crtc_vblank_end - 1) << 16), i); |
| + REG_WRITE_WITH_AUX(map->vsync, (adjusted_mode->crtc_vsync_start - 1) | |
| + ((adjusted_mode->crtc_vsync_end - 1) << 16), i); |
| + } |
| } |
| |
| /* Flush the plane changes */ |
| @@ -534,31 +559,35 @@ static int oaktrail_crtc_mode_set(struct |
| dpll |= DPLL_VCO_ENABLE; |
| |
| if (dpll & DPLL_VCO_ENABLE) { |
| - REG_WRITE(map->fp0, fp); |
| - REG_WRITE(map->dpll, dpll & ~DPLL_VCO_ENABLE); |
| - REG_READ(map->dpll); |
| - /* Check the DPLLA lock bit PIPEACONF[29] */ |
| - udelay(150); |
| + for (i = 0; i <= need_aux; i++) { |
| + REG_WRITE_WITH_AUX(map->fp0, fp, i); |
| + REG_WRITE_WITH_AUX(map->dpll, dpll & ~DPLL_VCO_ENABLE, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + /* Check the DPLLA lock bit PIPEACONF[29] */ |
| + udelay(150); |
| + } |
| } |
| |
| - REG_WRITE(map->fp0, fp); |
| - REG_WRITE(map->dpll, dpll); |
| - REG_READ(map->dpll); |
| - /* Wait for the clocks to stabilize. */ |
| - udelay(150); |
| - |
| - /* write it again -- the BIOS does, after all */ |
| - REG_WRITE(map->dpll, dpll); |
| - REG_READ(map->dpll); |
| - /* Wait for the clocks to stabilize. */ |
| - udelay(150); |
| - |
| - REG_WRITE(map->conf, pipeconf); |
| - REG_READ(map->conf); |
| - gma_wait_for_vblank(dev); |
| + for (i = 0; i <= need_aux; i++) { |
| + REG_WRITE_WITH_AUX(map->fp0, fp, i); |
| + REG_WRITE_WITH_AUX(map->dpll, dpll, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + /* Wait for the clocks to stabilize. */ |
| + udelay(150); |
| |
| - REG_WRITE(map->cntr, dspcntr); |
| - gma_wait_for_vblank(dev); |
| + /* write it again -- the BIOS does, after all */ |
| + REG_WRITE_WITH_AUX(map->dpll, dpll, i); |
| + REG_READ_WITH_AUX(map->dpll, i); |
| + /* Wait for the clocks to stabilize. */ |
| + udelay(150); |
| + |
| + REG_WRITE_WITH_AUX(map->conf, pipeconf, i); |
| + REG_READ_WITH_AUX(map->conf, i); |
| + gma_wait_for_vblank(dev); |
| + |
| + REG_WRITE_WITH_AUX(map->cntr, dspcntr, i); |
| + gma_wait_for_vblank(dev); |
| + } |
| |
| oaktrail_crtc_mode_set_exit: |
| gma_power_end(dev); |
| --- a/drivers/gpu/drm/gma500/psb_drv.h |
| +++ b/drivers/gpu/drm/gma500/psb_drv.h |
| @@ -940,6 +940,22 @@ static inline uint32_t REGISTER_READ_AUX |
| #define REG_READ(reg) REGISTER_READ(dev, (reg)) |
| #define REG_READ_AUX(reg) REGISTER_READ_AUX(dev, (reg)) |
| |
| +/* Useful for post reads */ |
| +static inline uint32_t REGISTER_READ_WITH_AUX(struct drm_device *dev, |
| + uint32_t reg, int aux) |
| +{ |
| + uint32_t val; |
| + |
| + if (aux) |
| + val = REG_READ_AUX(reg); |
| + else |
| + val = REG_READ(reg); |
| + |
| + return val; |
| +} |
| + |
| +#define REG_READ_WITH_AUX(reg, aux) REGISTER_READ_WITH_AUX(dev, (reg), (aux)) |
| + |
| static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, |
| uint32_t val) |
| { |
| @@ -957,6 +973,17 @@ static inline void REGISTER_WRITE_AUX(st |
| #define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) |
| #define REG_WRITE_AUX(reg, val) REGISTER_WRITE_AUX(dev, (reg), (val)) |
| |
| +static inline void REGISTER_WRITE_WITH_AUX(struct drm_device *dev, uint32_t reg, |
| + uint32_t val, int aux) |
| +{ |
| + if (aux) |
| + REG_WRITE_AUX(reg, val); |
| + else |
| + REG_WRITE(reg, val); |
| +} |
| + |
| +#define REG_WRITE_WITH_AUX(reg, val, aux) REGISTER_WRITE_WITH_AUX(dev, (reg), (val), (aux)) |
| + |
| static inline void REGISTER_WRITE16(struct drm_device *dev, |
| uint32_t reg, uint32_t val) |
| { |