Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright © 2006-2011 Intel Corporation
0004  *
0005  * Authors:
0006  *  Eric Anholt <eric@anholt.net>
0007  *  Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
0008  */
0009 
0010 #include <linux/delay.h>
0011 #include <linux/highmem.h>
0012 
0013 #include <drm/drm_crtc.h>
0014 #include <drm/drm_fourcc.h>
0015 #include <drm/drm_framebuffer.h>
0016 #include <drm/drm_vblank.h>
0017 
0018 #include "framebuffer.h"
0019 #include "gem.h"
0020 #include "gma_display.h"
0021 #include "psb_irq.h"
0022 #include "psb_intel_drv.h"
0023 #include "psb_intel_reg.h"
0024 
0025 /*
0026  * Returns whether any output on the specified pipe is of the specified type
0027  */
0028 bool gma_pipe_has_type(struct drm_crtc *crtc, int type)
0029 {
0030     struct drm_device *dev = crtc->dev;
0031     struct drm_connector_list_iter conn_iter;
0032     struct drm_connector *connector;
0033 
0034     drm_connector_list_iter_begin(dev, &conn_iter);
0035     drm_for_each_connector_iter(connector, &conn_iter) {
0036         if (connector->encoder && connector->encoder->crtc == crtc) {
0037             struct gma_encoder *gma_encoder =
0038                         gma_attached_encoder(connector);
0039             if (gma_encoder->type == type) {
0040                 drm_connector_list_iter_end(&conn_iter);
0041                 return true;
0042             }
0043         }
0044     }
0045     drm_connector_list_iter_end(&conn_iter);
0046 
0047     return false;
0048 }
0049 
0050 void gma_wait_for_vblank(struct drm_device *dev)
0051 {
0052     /* Wait for 20ms, i.e. one cycle at 50hz. */
0053     mdelay(20);
0054 }
0055 
0056 int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
0057               struct drm_framebuffer *old_fb)
0058 {
0059     struct drm_device *dev = crtc->dev;
0060     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0061     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0062     struct drm_framebuffer *fb = crtc->primary->fb;
0063     struct psb_gem_object *pobj;
0064     int pipe = gma_crtc->pipe;
0065     const struct psb_offset *map = &dev_priv->regmap[pipe];
0066     unsigned long start, offset;
0067     u32 dspcntr;
0068     int ret = 0;
0069 
0070     if (!gma_power_begin(dev, true))
0071         return 0;
0072 
0073     /* no fb bound */
0074     if (!fb) {
0075         dev_err(dev->dev, "No FB bound\n");
0076         goto gma_pipe_cleaner;
0077     }
0078 
0079     pobj = to_psb_gem_object(fb->obj[0]);
0080 
0081     /* We are displaying this buffer, make sure it is actually loaded
0082        into the GTT */
0083     ret = psb_gem_pin(pobj);
0084     if (ret < 0)
0085         goto gma_pipe_set_base_exit;
0086     start = pobj->offset;
0087     offset = y * fb->pitches[0] + x * fb->format->cpp[0];
0088 
0089     REG_WRITE(map->stride, fb->pitches[0]);
0090 
0091     dspcntr = REG_READ(map->cntr);
0092     dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
0093 
0094     switch (fb->format->cpp[0] * 8) {
0095     case 8:
0096         dspcntr |= DISPPLANE_8BPP;
0097         break;
0098     case 16:
0099         if (fb->format->depth == 15)
0100             dspcntr |= DISPPLANE_15_16BPP;
0101         else
0102             dspcntr |= DISPPLANE_16BPP;
0103         break;
0104     case 24:
0105     case 32:
0106         dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
0107         break;
0108     default:
0109         dev_err(dev->dev, "Unknown color depth\n");
0110         ret = -EINVAL;
0111         goto gma_pipe_set_base_exit;
0112     }
0113     REG_WRITE(map->cntr, dspcntr);
0114 
0115     dev_dbg(dev->dev,
0116         "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
0117 
0118     /* FIXME: Investigate whether this really is the base for psb and why
0119           the linear offset is named base for the other chips. map->surf
0120           should be the base and map->linoff the offset for all chips */
0121     if (IS_PSB(dev)) {
0122         REG_WRITE(map->base, offset + start);
0123         REG_READ(map->base);
0124     } else {
0125         REG_WRITE(map->base, offset);
0126         REG_READ(map->base);
0127         REG_WRITE(map->surf, start);
0128         REG_READ(map->surf);
0129     }
0130 
0131 gma_pipe_cleaner:
0132     /* If there was a previous display we can now unpin it */
0133     if (old_fb)
0134         psb_gem_unpin(to_psb_gem_object(old_fb->obj[0]));
0135 
0136 gma_pipe_set_base_exit:
0137     gma_power_end(dev);
0138     return ret;
0139 }
0140 
0141 /* Loads the palette/gamma unit for the CRTC with the prepared values */
0142 void gma_crtc_load_lut(struct drm_crtc *crtc)
0143 {
0144     struct drm_device *dev = crtc->dev;
0145     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0146     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0147     const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe];
0148     int palreg = map->palette;
0149     u16 *r, *g, *b;
0150     int i;
0151 
0152     /* The clocks have to be on to load the palette. */
0153     if (!crtc->enabled)
0154         return;
0155 
0156     r = crtc->gamma_store;
0157     g = r + crtc->gamma_size;
0158     b = g + crtc->gamma_size;
0159 
0160     if (gma_power_begin(dev, false)) {
0161         for (i = 0; i < 256; i++) {
0162             REG_WRITE(palreg + 4 * i,
0163                   (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) |
0164                   (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) |
0165                   ((*b++ >> 8) + gma_crtc->lut_adj[i]));
0166         }
0167         gma_power_end(dev);
0168     } else {
0169         for (i = 0; i < 256; i++) {
0170             /* FIXME: Why pipe[0] and not pipe[..._crtc->pipe]? */
0171             dev_priv->regs.pipe[0].palette[i] =
0172                 (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) |
0173                 (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) |
0174                 ((*b++ >> 8) + gma_crtc->lut_adj[i]);
0175         }
0176 
0177     }
0178 }
0179 
0180 static int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
0181                   u16 *blue, u32 size,
0182                   struct drm_modeset_acquire_ctx *ctx)
0183 {
0184     gma_crtc_load_lut(crtc);
0185 
0186     return 0;
0187 }
0188 
0189 /*
0190  * Sets the power management mode of the pipe and plane.
0191  *
0192  * This code should probably grow support for turning the cursor off and back
0193  * on appropriately at the same time as we're turning the pipe off/on.
0194  */
0195 void gma_crtc_dpms(struct drm_crtc *crtc, int mode)
0196 {
0197     struct drm_device *dev = crtc->dev;
0198     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0199     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0200     int pipe = gma_crtc->pipe;
0201     const struct psb_offset *map = &dev_priv->regmap[pipe];
0202     u32 temp;
0203 
0204     /* XXX: When our outputs are all unaware of DPMS modes other than off
0205      * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
0206      */
0207 
0208     if (IS_CDV(dev))
0209         dev_priv->ops->disable_sr(dev);
0210 
0211     switch (mode) {
0212     case DRM_MODE_DPMS_ON:
0213     case DRM_MODE_DPMS_STANDBY:
0214     case DRM_MODE_DPMS_SUSPEND:
0215         if (gma_crtc->active)
0216             break;
0217 
0218         gma_crtc->active = true;
0219 
0220         /* Enable the DPLL */
0221         temp = REG_READ(map->dpll);
0222         if ((temp & DPLL_VCO_ENABLE) == 0) {
0223             REG_WRITE(map->dpll, temp);
0224             REG_READ(map->dpll);
0225             /* Wait for the clocks to stabilize. */
0226             udelay(150);
0227             REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
0228             REG_READ(map->dpll);
0229             /* Wait for the clocks to stabilize. */
0230             udelay(150);
0231             REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
0232             REG_READ(map->dpll);
0233             /* Wait for the clocks to stabilize. */
0234             udelay(150);
0235         }
0236 
0237         /* Enable the plane */
0238         temp = REG_READ(map->cntr);
0239         if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
0240             REG_WRITE(map->cntr,
0241                   temp | DISPLAY_PLANE_ENABLE);
0242             /* Flush the plane changes */
0243             REG_WRITE(map->base, REG_READ(map->base));
0244         }
0245 
0246         udelay(150);
0247 
0248         /* Enable the pipe */
0249         temp = REG_READ(map->conf);
0250         if ((temp & PIPEACONF_ENABLE) == 0)
0251             REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
0252 
0253         temp = REG_READ(map->status);
0254         temp &= ~(0xFFFF);
0255         temp |= PIPE_FIFO_UNDERRUN;
0256         REG_WRITE(map->status, temp);
0257         REG_READ(map->status);
0258 
0259         gma_crtc_load_lut(crtc);
0260 
0261         /* Give the overlay scaler a chance to enable
0262          * if it's on this pipe */
0263         /* psb_intel_crtc_dpms_video(crtc, true); TODO */
0264 
0265         drm_crtc_vblank_on(crtc);
0266         break;
0267     case DRM_MODE_DPMS_OFF:
0268         if (!gma_crtc->active)
0269             break;
0270 
0271         gma_crtc->active = false;
0272 
0273         /* Give the overlay scaler a chance to disable
0274          * if it's on this pipe */
0275         /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
0276 
0277         /* Disable the VGA plane that we never use */
0278         REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
0279 
0280         /* Turn off vblank interrupts */
0281         drm_crtc_vblank_off(crtc);
0282 
0283         /* Wait for vblank for the disable to take effect */
0284         gma_wait_for_vblank(dev);
0285 
0286         /* Disable plane */
0287         temp = REG_READ(map->cntr);
0288         if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
0289             REG_WRITE(map->cntr,
0290                   temp & ~DISPLAY_PLANE_ENABLE);
0291             /* Flush the plane changes */
0292             REG_WRITE(map->base, REG_READ(map->base));
0293             REG_READ(map->base);
0294         }
0295 
0296         /* Disable pipe */
0297         temp = REG_READ(map->conf);
0298         if ((temp & PIPEACONF_ENABLE) != 0) {
0299             REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE);
0300             REG_READ(map->conf);
0301         }
0302 
0303         /* Wait for vblank for the disable to take effect. */
0304         gma_wait_for_vblank(dev);
0305 
0306         udelay(150);
0307 
0308         /* Disable DPLL */
0309         temp = REG_READ(map->dpll);
0310         if ((temp & DPLL_VCO_ENABLE) != 0) {
0311             REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE);
0312             REG_READ(map->dpll);
0313         }
0314 
0315         /* Wait for the clocks to turn off. */
0316         udelay(150);
0317         break;
0318     }
0319 
0320     if (IS_CDV(dev))
0321         dev_priv->ops->update_wm(dev, crtc);
0322 
0323     /* Set FIFO watermarks */
0324     REG_WRITE(DSPARB, 0x3F3E);
0325 }
0326 
0327 static int gma_crtc_cursor_set(struct drm_crtc *crtc,
0328                    struct drm_file *file_priv, uint32_t handle,
0329                    uint32_t width, uint32_t height)
0330 {
0331     struct drm_device *dev = crtc->dev;
0332     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0333     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0334     int pipe = gma_crtc->pipe;
0335     uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
0336     uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
0337     uint32_t temp;
0338     size_t addr = 0;
0339     struct psb_gem_object *pobj;
0340     struct psb_gem_object *cursor_pobj = gma_crtc->cursor_pobj;
0341     struct drm_gem_object *obj;
0342     void *tmp_dst;
0343     int ret = 0, i, cursor_pages;
0344 
0345     /* If we didn't get a handle then turn the cursor off */
0346     if (!handle) {
0347         temp = CURSOR_MODE_DISABLE;
0348         if (gma_power_begin(dev, false)) {
0349             REG_WRITE(control, temp);
0350             REG_WRITE(base, 0);
0351             gma_power_end(dev);
0352         }
0353 
0354         /* Unpin the old GEM object */
0355         if (gma_crtc->cursor_obj) {
0356             pobj = to_psb_gem_object(gma_crtc->cursor_obj);
0357             psb_gem_unpin(pobj);
0358             drm_gem_object_put(gma_crtc->cursor_obj);
0359             gma_crtc->cursor_obj = NULL;
0360         }
0361         return 0;
0362     }
0363 
0364     /* Currently we only support 64x64 cursors */
0365     if (width != 64 || height != 64) {
0366         dev_dbg(dev->dev, "We currently only support 64x64 cursors\n");
0367         return -EINVAL;
0368     }
0369 
0370     obj = drm_gem_object_lookup(file_priv, handle);
0371     if (!obj) {
0372         ret = -ENOENT;
0373         goto unlock;
0374     }
0375 
0376     if (obj->size < width * height * 4) {
0377         dev_dbg(dev->dev, "Buffer is too small\n");
0378         ret = -ENOMEM;
0379         goto unref_cursor;
0380     }
0381 
0382     pobj = to_psb_gem_object(obj);
0383 
0384     /* Pin the memory into the GTT */
0385     ret = psb_gem_pin(pobj);
0386     if (ret) {
0387         dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
0388         goto unref_cursor;
0389     }
0390 
0391     if (dev_priv->ops->cursor_needs_phys) {
0392         if (!cursor_pobj) {
0393             dev_err(dev->dev, "No hardware cursor mem available");
0394             ret = -ENOMEM;
0395             goto unref_cursor;
0396         }
0397 
0398         cursor_pages = obj->size / PAGE_SIZE;
0399         if (cursor_pages > 4)
0400             cursor_pages = 4; /* Prevent overflow */
0401 
0402         /* Copy the cursor to cursor mem */
0403         tmp_dst = dev_priv->vram_addr + cursor_pobj->offset;
0404         for (i = 0; i < cursor_pages; i++) {
0405             memcpy_from_page(tmp_dst, pobj->pages[i], 0, PAGE_SIZE);
0406             tmp_dst += PAGE_SIZE;
0407         }
0408 
0409         addr = gma_crtc->cursor_addr;
0410     } else {
0411         addr = pobj->offset;
0412         gma_crtc->cursor_addr = addr;
0413     }
0414 
0415     temp = 0;
0416     /* set the pipe for the cursor */
0417     temp |= (pipe << 28);
0418     temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
0419 
0420     if (gma_power_begin(dev, false)) {
0421         REG_WRITE(control, temp);
0422         REG_WRITE(base, addr);
0423         gma_power_end(dev);
0424     }
0425 
0426     /* unpin the old bo */
0427     if (gma_crtc->cursor_obj) {
0428         pobj = to_psb_gem_object(gma_crtc->cursor_obj);
0429         psb_gem_unpin(pobj);
0430         drm_gem_object_put(gma_crtc->cursor_obj);
0431     }
0432 
0433     gma_crtc->cursor_obj = obj;
0434 unlock:
0435     return ret;
0436 
0437 unref_cursor:
0438     drm_gem_object_put(obj);
0439     return ret;
0440 }
0441 
0442 static int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
0443 {
0444     struct drm_device *dev = crtc->dev;
0445     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0446     int pipe = gma_crtc->pipe;
0447     uint32_t temp = 0;
0448     uint32_t addr;
0449 
0450     if (x < 0) {
0451         temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
0452         x = -x;
0453     }
0454     if (y < 0) {
0455         temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
0456         y = -y;
0457     }
0458 
0459     temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
0460     temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
0461 
0462     addr = gma_crtc->cursor_addr;
0463 
0464     if (gma_power_begin(dev, false)) {
0465         REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
0466         REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
0467         gma_power_end(dev);
0468     }
0469     return 0;
0470 }
0471 
0472 void gma_crtc_prepare(struct drm_crtc *crtc)
0473 {
0474     const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0475     crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
0476 }
0477 
0478 void gma_crtc_commit(struct drm_crtc *crtc)
0479 {
0480     const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0481     crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
0482 }
0483 
0484 void gma_crtc_disable(struct drm_crtc *crtc)
0485 {
0486     struct psb_gem_object *pobj;
0487     const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0488 
0489     crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
0490 
0491     if (crtc->primary->fb) {
0492         pobj = to_psb_gem_object(crtc->primary->fb->obj[0]);
0493         psb_gem_unpin(pobj);
0494     }
0495 }
0496 
0497 void gma_crtc_destroy(struct drm_crtc *crtc)
0498 {
0499     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0500 
0501     if (gma_crtc->cursor_pobj)
0502         drm_gem_object_put(&gma_crtc->cursor_pobj->base);
0503 
0504     kfree(gma_crtc->crtc_state);
0505     drm_crtc_cleanup(crtc);
0506     kfree(gma_crtc);
0507 }
0508 
0509 int gma_crtc_page_flip(struct drm_crtc *crtc,
0510                struct drm_framebuffer *fb,
0511                struct drm_pending_vblank_event *event,
0512                uint32_t page_flip_flags,
0513                struct drm_modeset_acquire_ctx *ctx)
0514 {
0515     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0516     struct drm_framebuffer *current_fb = crtc->primary->fb;
0517     struct drm_framebuffer *old_fb = crtc->primary->old_fb;
0518     const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0519     struct drm_device *dev = crtc->dev;
0520     unsigned long flags;
0521     int ret;
0522 
0523     if (!crtc_funcs->mode_set_base)
0524         return -EINVAL;
0525 
0526     /* Using mode_set_base requires the new fb to be set already. */
0527     crtc->primary->fb = fb;
0528 
0529     if (event) {
0530         spin_lock_irqsave(&dev->event_lock, flags);
0531 
0532         WARN_ON(drm_crtc_vblank_get(crtc) != 0);
0533 
0534         gma_crtc->page_flip_event = event;
0535         spin_unlock_irqrestore(&dev->event_lock, flags);
0536 
0537         /* Call this locked if we want an event at vblank interrupt. */
0538         ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
0539         if (ret) {
0540             spin_lock_irqsave(&dev->event_lock, flags);
0541             if (gma_crtc->page_flip_event) {
0542                 gma_crtc->page_flip_event = NULL;
0543                 drm_crtc_vblank_put(crtc);
0544             }
0545             spin_unlock_irqrestore(&dev->event_lock, flags);
0546         }
0547     } else {
0548         ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
0549     }
0550 
0551     /* Restore previous fb in case of failure. */
0552     if (ret)
0553         crtc->primary->fb = current_fb;
0554 
0555     return ret;
0556 }
0557 
0558 int gma_crtc_set_config(struct drm_mode_set *set,
0559             struct drm_modeset_acquire_ctx *ctx)
0560 {
0561     struct drm_device *dev = set->crtc->dev;
0562     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0563     int ret;
0564 
0565     if (!dev_priv->rpm_enabled)
0566         return drm_crtc_helper_set_config(set, ctx);
0567 
0568     pm_runtime_forbid(dev->dev);
0569     ret = drm_crtc_helper_set_config(set, ctx);
0570     pm_runtime_allow(dev->dev);
0571 
0572     return ret;
0573 }
0574 
0575 const struct drm_crtc_funcs gma_crtc_funcs = {
0576     .cursor_set = gma_crtc_cursor_set,
0577     .cursor_move = gma_crtc_cursor_move,
0578     .gamma_set = gma_crtc_gamma_set,
0579     .set_config = gma_crtc_set_config,
0580     .destroy = gma_crtc_destroy,
0581     .page_flip = gma_crtc_page_flip,
0582     .enable_vblank = gma_crtc_enable_vblank,
0583     .disable_vblank = gma_crtc_disable_vblank,
0584     .get_vblank_counter = gma_crtc_get_vblank_counter,
0585 };
0586 
0587 /*
0588  * Save HW states of given crtc
0589  */
0590 void gma_crtc_save(struct drm_crtc *crtc)
0591 {
0592     struct drm_device *dev = crtc->dev;
0593     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0594     struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
0595     struct psb_intel_crtc_state *crtc_state = gma_crtc->crtc_state;
0596     const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe];
0597     uint32_t palette_reg;
0598     int i;
0599 
0600     if (!crtc_state) {
0601         dev_err(dev->dev, "No CRTC state found\n");
0602         return;
0603     }
0604 
0605     crtc_state->saveDSPCNTR = REG_READ(map->cntr);
0606     crtc_state->savePIPECONF = REG_READ(map->conf);
0607     crtc_state->savePIPESRC = REG_READ(map->src);
0608     crtc_state->saveFP0 = REG_READ(map->fp0);
0609     crtc_state->saveFP1 = REG_READ(map->fp1);
0610     crtc_state->saveDPLL = REG_READ(map->dpll);
0611     crtc_state->saveHTOTAL = REG_READ(map->htotal);
0612     crtc_state->saveHBLANK = REG_READ(map->hblank);
0613     crtc_state->saveHSYNC = REG_READ(map->hsync);
0614     crtc_state->saveVTOTAL = REG_READ(map->vtotal);
0615     crtc_state->saveVBLANK = REG_READ(map->vblank);
0616     crtc_state->saveVSYNC = REG_READ(map->vsync);
0617     crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
0618 
0619     /* NOTE: DSPSIZE DSPPOS only for psb */
0620     crtc_state->saveDSPSIZE = REG_READ(map->size);
0621     crtc_state->saveDSPPOS = REG_READ(map->pos);
0622 
0623     crtc_state->saveDSPBASE = REG_READ(map->base);
0624 
0625     palette_reg = map->palette;
0626     for (i = 0; i < 256; ++i)
0627         crtc_state->savePalette[i] = REG_READ(palette_reg + (i << 2));
0628 }
0629 
0630 /*
0631  * Restore HW states of given crtc
0632  */
0633 void gma_crtc_restore(struct drm_crtc *crtc)
0634 {
0635     struct drm_device *dev = crtc->dev;
0636     struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
0637     struct gma_crtc *gma_crtc =  to_gma_crtc(crtc);
0638     struct psb_intel_crtc_state *crtc_state = gma_crtc->crtc_state;
0639     const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe];
0640     uint32_t palette_reg;
0641     int i;
0642 
0643     if (!crtc_state) {
0644         dev_err(dev->dev, "No crtc state\n");
0645         return;
0646     }
0647 
0648     if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
0649         REG_WRITE(map->dpll,
0650             crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
0651         REG_READ(map->dpll);
0652         udelay(150);
0653     }
0654 
0655     REG_WRITE(map->fp0, crtc_state->saveFP0);
0656     REG_READ(map->fp0);
0657 
0658     REG_WRITE(map->fp1, crtc_state->saveFP1);
0659     REG_READ(map->fp1);
0660 
0661     REG_WRITE(map->dpll, crtc_state->saveDPLL);
0662     REG_READ(map->dpll);
0663     udelay(150);
0664 
0665     REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
0666     REG_WRITE(map->hblank, crtc_state->saveHBLANK);
0667     REG_WRITE(map->hsync, crtc_state->saveHSYNC);
0668     REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
0669     REG_WRITE(map->vblank, crtc_state->saveVBLANK);
0670     REG_WRITE(map->vsync, crtc_state->saveVSYNC);
0671     REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
0672 
0673     REG_WRITE(map->size, crtc_state->saveDSPSIZE);
0674     REG_WRITE(map->pos, crtc_state->saveDSPPOS);
0675 
0676     REG_WRITE(map->src, crtc_state->savePIPESRC);
0677     REG_WRITE(map->base, crtc_state->saveDSPBASE);
0678     REG_WRITE(map->conf, crtc_state->savePIPECONF);
0679 
0680     gma_wait_for_vblank(dev);
0681 
0682     REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
0683     REG_WRITE(map->base, crtc_state->saveDSPBASE);
0684 
0685     gma_wait_for_vblank(dev);
0686 
0687     palette_reg = map->palette;
0688     for (i = 0; i < 256; ++i)
0689         REG_WRITE(palette_reg + (i << 2), crtc_state->savePalette[i]);
0690 }
0691 
0692 void gma_encoder_prepare(struct drm_encoder *encoder)
0693 {
0694     const struct drm_encoder_helper_funcs *encoder_funcs =
0695         encoder->helper_private;
0696     /* lvds has its own version of prepare see psb_intel_lvds_prepare */
0697     encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
0698 }
0699 
0700 void gma_encoder_commit(struct drm_encoder *encoder)
0701 {
0702     const struct drm_encoder_helper_funcs *encoder_funcs =
0703         encoder->helper_private;
0704     /* lvds has its own version of commit see psb_intel_lvds_commit */
0705     encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
0706 }
0707 
0708 void gma_encoder_destroy(struct drm_encoder *encoder)
0709 {
0710     struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
0711 
0712     drm_encoder_cleanup(encoder);
0713     kfree(intel_encoder);
0714 }
0715 
0716 /* Currently there is only a 1:1 mapping of encoders and connectors */
0717 struct drm_encoder *gma_best_encoder(struct drm_connector *connector)
0718 {
0719     struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
0720 
0721     return &gma_encoder->base;
0722 }
0723 
0724 void gma_connector_attach_encoder(struct gma_connector *connector,
0725                   struct gma_encoder *encoder)
0726 {
0727     connector->encoder = encoder;
0728     drm_connector_attach_encoder(&connector->base,
0729                       &encoder->base);
0730 }
0731 
0732 #define GMA_PLL_INVALID(s) { /* DRM_ERROR(s); */ return false; }
0733 
0734 bool gma_pll_is_valid(struct drm_crtc *crtc,
0735               const struct gma_limit_t *limit,
0736               struct gma_clock_t *clock)
0737 {
0738     if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
0739         GMA_PLL_INVALID("p1 out of range");
0740     if (clock->p < limit->p.min || limit->p.max < clock->p)
0741         GMA_PLL_INVALID("p out of range");
0742     if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
0743         GMA_PLL_INVALID("m2 out of range");
0744     if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
0745         GMA_PLL_INVALID("m1 out of range");
0746     /* On CDV m1 is always 0 */
0747     if (clock->m1 <= clock->m2 && clock->m1 != 0)
0748         GMA_PLL_INVALID("m1 <= m2 && m1 != 0");
0749     if (clock->m < limit->m.min || limit->m.max < clock->m)
0750         GMA_PLL_INVALID("m out of range");
0751     if (clock->n < limit->n.min || limit->n.max < clock->n)
0752         GMA_PLL_INVALID("n out of range");
0753     if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
0754         GMA_PLL_INVALID("vco out of range");
0755     /* XXX: We may need to be checking "Dot clock"
0756      * depending on the multiplier, connector, etc.,
0757      * rather than just a single range.
0758      */
0759     if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
0760         GMA_PLL_INVALID("dot out of range");
0761 
0762     return true;
0763 }
0764 
0765 bool gma_find_best_pll(const struct gma_limit_t *limit,
0766                struct drm_crtc *crtc, int target, int refclk,
0767                struct gma_clock_t *best_clock)
0768 {
0769     struct drm_device *dev = crtc->dev;
0770     const struct gma_clock_funcs *clock_funcs =
0771                         to_gma_crtc(crtc)->clock_funcs;
0772     struct gma_clock_t clock;
0773     int err = target;
0774 
0775     if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
0776         (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
0777         /*
0778          * For LVDS, if the panel is on, just rely on its current
0779          * settings for dual-channel.  We haven't figured out how to
0780          * reliably set up different single/dual channel state, if we
0781          * even can.
0782          */
0783         if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
0784             LVDS_CLKB_POWER_UP)
0785             clock.p2 = limit->p2.p2_fast;
0786         else
0787             clock.p2 = limit->p2.p2_slow;
0788     } else {
0789         if (target < limit->p2.dot_limit)
0790             clock.p2 = limit->p2.p2_slow;
0791         else
0792             clock.p2 = limit->p2.p2_fast;
0793     }
0794 
0795     memset(best_clock, 0, sizeof(*best_clock));
0796 
0797     /* m1 is always 0 on CDV so the outmost loop will run just once */
0798     for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
0799         for (clock.m2 = limit->m2.min;
0800              (clock.m2 < clock.m1 || clock.m1 == 0) &&
0801               clock.m2 <= limit->m2.max; clock.m2++) {
0802             for (clock.n = limit->n.min;
0803                  clock.n <= limit->n.max; clock.n++) {
0804                 for (clock.p1 = limit->p1.min;
0805                      clock.p1 <= limit->p1.max;
0806                      clock.p1++) {
0807                     int this_err;
0808 
0809                     clock_funcs->clock(refclk, &clock);
0810 
0811                     if (!clock_funcs->pll_is_valid(crtc,
0812                                 limit, &clock))
0813                         continue;
0814 
0815                     this_err = abs(clock.dot - target);
0816                     if (this_err < err) {
0817                         *best_clock = clock;
0818                         err = this_err;
0819                     }
0820                 }
0821             }
0822         }
0823     }
0824 
0825     return err != target;
0826 }