Merge branch 'gma500-next' of git://github.com/patjak/drm-gma500 into drm-next
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / gpu / drm / gma500 / gtt.c
index 054e26e769ec1b2eb7ecfff544e412cc2b6f70ed..1f82183536a32014f0d73af7fea740489476ab35 100644 (file)
@@ -80,7 +80,8 @@ static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
  *     the GTT. This is protected via the gtt mutex which the caller
  *     must hold.
  */
-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
+static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
+                         int resume)
 {
        u32 __iomem *gtt_slot;
        u32 pte;
@@ -97,8 +98,10 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
        gtt_slot = psb_gtt_entry(dev, r);
        pages = r->pages;
 
-       /* Make sure changes are visible to the GPU */
-       set_pages_array_wc(pages, r->npage);
+       if (!resume) {
+               /* Make sure changes are visible to the GPU */
+               set_pages_array_wc(pages, r->npage);
+       }
 
        /* Write our page entries into the GTT itself */
        for (i = r->roll; i < r->npage; i++) {
@@ -269,7 +272,7 @@ int psb_gtt_pin(struct gtt_range *gt)
                ret = psb_gtt_attach_pages(gt);
                if (ret < 0)
                        goto out;
-               ret = psb_gtt_insert(dev, gt);
+               ret = psb_gtt_insert(dev, gt, 0);
                if (ret < 0) {
                        psb_gtt_detach_pages(gt);
                        goto out;
@@ -421,9 +424,11 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        int ret = 0;
        uint32_t pte;
 
-       mutex_init(&dev_priv->gtt_mutex);
+       if (!resume) {
+               mutex_init(&dev_priv->gtt_mutex);
+               psb_gtt_alloc(dev);
+       }
 
-       psb_gtt_alloc(dev);
        pg = &dev_priv->gtt;
 
        /* Enable the GTT */
@@ -505,7 +510,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        /*
         *      Map the GTT and the stolen memory area
         */
-       dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
+       if (!resume)
+               dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
                                                gtt_pages << PAGE_SHIFT);
        if (!dev_priv->gtt_map) {
                dev_err(dev->dev, "Failure to map gtt.\n");
@@ -513,7 +519,9 @@ int psb_gtt_init(struct drm_device *dev, int resume)
                goto out_err;
        }
 
-       dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
+       if (!resume)
+               dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base,
+                                                stolen_size);
        if (!dev_priv->vram_addr) {
                dev_err(dev->dev, "Failure to map stolen base.\n");
                ret = -ENOMEM;
@@ -549,3 +557,31 @@ out_err:
        psb_gtt_takedown(dev);
        return ret;
 }
+
+int psb_gtt_restore(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct resource *r = dev_priv->gtt_mem->child;
+       struct gtt_range *range;
+       unsigned int restored = 0, total = 0, size = 0;
+
+       /* On resume, the gtt_mutex is already initialized */
+       mutex_lock(&dev_priv->gtt_mutex);
+       psb_gtt_init(dev, 1);
+
+       while (r != NULL) {
+               range = container_of(r, struct gtt_range, resource);
+               if (range->pages) {
+                       psb_gtt_insert(dev, range, 1);
+                       size += range->resource.end - range->resource.start;
+                       restored++;
+               }
+               r = r->sibling;
+               total++;
+       }
+       mutex_unlock(&dev_priv->gtt_mutex);
+       DRM_DEBUG_DRIVER("Restored %u of %u gtt ranges (%u KB)", restored,
+                        total, (size / 1024));
+
+       return 0;
+}