drm/gma500: Add generic crtc save/restore funcs
authorPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Fri, 12 Jul 2013 13:30:56 +0000 (15:30 +0200)
committerPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Tue, 23 Jul 2013 23:47:30 +0000 (01:47 +0200)
Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/gma_display.h

index 67d86d8fcd4d5a92f02088877cc1547b28e76ba8..cca40c0b64e4d5601e717dc96139509b6e818ecd 100644 (file)
@@ -519,6 +519,111 @@ void gma_crtc_destroy(struct drm_crtc *crtc)
        kfree(psb_intel_crtc);
 }
 
+/**
+ * Save HW states of given crtc
+ */
+void gma_crtc_save(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
+       uint32_t palette_reg;
+       int i;
+
+       if (!crtc_state) {
+               dev_err(dev->dev, "No CRTC state found\n");
+               return;
+       }
+
+       crtc_state->saveDSPCNTR = REG_READ(map->cntr);
+       crtc_state->savePIPECONF = REG_READ(map->conf);
+       crtc_state->savePIPESRC = REG_READ(map->src);
+       crtc_state->saveFP0 = REG_READ(map->fp0);
+       crtc_state->saveFP1 = REG_READ(map->fp1);
+       crtc_state->saveDPLL = REG_READ(map->dpll);
+       crtc_state->saveHTOTAL = REG_READ(map->htotal);
+       crtc_state->saveHBLANK = REG_READ(map->hblank);
+       crtc_state->saveHSYNC = REG_READ(map->hsync);
+       crtc_state->saveVTOTAL = REG_READ(map->vtotal);
+       crtc_state->saveVBLANK = REG_READ(map->vblank);
+       crtc_state->saveVSYNC = REG_READ(map->vsync);
+       crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
+
+       /* NOTE: DSPSIZE DSPPOS only for psb */
+       crtc_state->saveDSPSIZE = REG_READ(map->size);
+       crtc_state->saveDSPPOS = REG_READ(map->pos);
+
+       crtc_state->saveDSPBASE = REG_READ(map->base);
+
+       palette_reg = map->palette;
+       for (i = 0; i < 256; ++i)
+               crtc_state->savePalette[i] = REG_READ(palette_reg + (i << 2));
+}
+
+/**
+ * Restore HW states of given crtc
+ */
+void gma_crtc_restore(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
+       struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
+       uint32_t palette_reg;
+       int i;
+
+       if (!crtc_state) {
+               dev_err(dev->dev, "No crtc state\n");
+               return;
+       }
+
+       if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+               REG_WRITE(map->dpll,
+                       crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+               REG_READ(map->dpll);
+               udelay(150);
+       }
+
+       REG_WRITE(map->fp0, crtc_state->saveFP0);
+       REG_READ(map->fp0);
+
+       REG_WRITE(map->fp1, crtc_state->saveFP1);
+       REG_READ(map->fp1);
+
+       REG_WRITE(map->dpll, crtc_state->saveDPLL);
+       REG_READ(map->dpll);
+       udelay(150);
+
+       REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
+       REG_WRITE(map->hblank, crtc_state->saveHBLANK);
+       REG_WRITE(map->hsync, crtc_state->saveHSYNC);
+       REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
+       REG_WRITE(map->vblank, crtc_state->saveVBLANK);
+       REG_WRITE(map->vsync, crtc_state->saveVSYNC);
+       REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
+
+       REG_WRITE(map->size, crtc_state->saveDSPSIZE);
+       REG_WRITE(map->pos, crtc_state->saveDSPPOS);
+
+       REG_WRITE(map->src, crtc_state->savePIPESRC);
+       REG_WRITE(map->base, crtc_state->saveDSPBASE);
+       REG_WRITE(map->conf, crtc_state->savePIPECONF);
+
+       gma_wait_for_vblank(dev);
+
+       REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
+       REG_WRITE(map->base, crtc_state->saveDSPBASE);
+
+       gma_wait_for_vblank(dev);
+
+       palette_reg = map->palette;
+       for (i = 0; i < 256; ++i)
+               REG_WRITE(palette_reg + (i << 2), crtc_state->savePalette[i]);
+}
+
 void gma_encoder_prepare(struct drm_encoder *encoder)
 {
        struct drm_encoder_helper_funcs *encoder_funcs =
index 1e7016529d75378eefd6d89cad6e1e7c42b8405d..8847de0695164e03bfa2ff83f012e6068a8647b0 100644 (file)
@@ -81,6 +81,9 @@ extern void gma_crtc_commit(struct drm_crtc *crtc);
 extern void gma_crtc_disable(struct drm_crtc *crtc);
 extern void gma_crtc_destroy(struct drm_crtc *crtc);
 
+extern void gma_crtc_save(struct drm_crtc *crtc);
+extern void gma_crtc_restore(struct drm_crtc *crtc);
+
 extern void gma_encoder_prepare(struct drm_encoder *encoder);
 extern void gma_encoder_commit(struct drm_encoder *encoder);
 extern void gma_encoder_destroy(struct drm_encoder *encoder);