ASoC: Intel: Move capture PCM pin to PCM0 for Broadwell/Haswell
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / i915_gem_render_state.c
index 34894b57306401645a2184d48d99ed2966c8c9f1..a9a62d75aa577daa015543c7955c25cd5bf5b42a 100644 (file)
 #include "i915_drv.h"
 #include "intel_renderstate.h"
 
-struct i915_render_state {
-       struct drm_i915_gem_object *obj;
-       unsigned long ggtt_offset;
-       u32 *batch;
-       u32 size;
-       u32 len;
-};
-
-static struct i915_render_state *render_state_alloc(struct drm_device *dev)
-{
-       struct i915_render_state *so;
-       struct page *page;
-       int ret;
-
-       so = kzalloc(sizeof(*so), GFP_KERNEL);
-       if (!so)
-               return ERR_PTR(-ENOMEM);
-
-       so->obj = i915_gem_alloc_object(dev, 4096);
-       if (so->obj == NULL) {
-               ret = -ENOMEM;
-               goto free;
-       }
-       so->size = 4096;
-
-       ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0);
-       if (ret)
-               goto free_gem;
-
-       BUG_ON(so->obj->pages->nents != 1);
-       page = sg_page(so->obj->pages->sgl);
-
-       so->batch = kmap(page);
-       if (!so->batch) {
-               ret = -ENOMEM;
-               goto unpin;
-       }
-
-       so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj);
-
-       return so;
-unpin:
-       i915_gem_object_ggtt_unpin(so->obj);
-free_gem:
-       drm_gem_object_unreference(&so->obj->base);
-free:
-       kfree(so);
-       return ERR_PTR(ret);
-}
-
-static void render_state_free(struct i915_render_state *so)
-{
-       kunmap(kmap_to_page(so->batch));
-       i915_gem_object_ggtt_unpin(so->obj);
-       drm_gem_object_unreference(&so->obj->base);
-       kfree(so);
-}
-
 static const struct intel_renderstate_rodata *
 render_state_get_rodata(struct drm_device *dev, const int gen)
 {
@@ -101,98 +43,137 @@ render_state_get_rodata(struct drm_device *dev, const int gen)
        return NULL;
 }
 
-static int render_state_setup(const int gen,
-                             const struct intel_renderstate_rodata *rodata,
-                             struct i915_render_state *so)
+static int render_state_init(struct render_state *so, struct drm_device *dev)
 {
-       const u64 goffset = i915_gem_obj_ggtt_offset(so->obj);
-       u32 reloc_index = 0;
-       u32 * const d = so->batch;
-       unsigned int i = 0;
        int ret;
 
-       if (!rodata || rodata->batch_items * 4 > so->size)
+       so->gen = INTEL_INFO(dev)->gen;
+       so->rodata = render_state_get_rodata(dev, so->gen);
+       if (so->rodata == NULL)
+               return 0;
+
+       if (so->rodata->batch_items * 4 > 4096)
                return -EINVAL;
 
+       so->obj = i915_gem_alloc_object(dev, 4096);
+       if (so->obj == NULL)
+               return -ENOMEM;
+
+       ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0);
+       if (ret)
+               goto free_gem;
+
+       so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj);
+       return 0;
+
+free_gem:
+       drm_gem_object_unreference(&so->obj->base);
+       return ret;
+}
+
+static int render_state_setup(struct render_state *so)
+{
+       const struct intel_renderstate_rodata *rodata = so->rodata;
+       unsigned int i = 0, reloc_index = 0;
+       struct page *page;
+       u32 *d;
+       int ret;
+
        ret = i915_gem_object_set_to_cpu_domain(so->obj, true);
        if (ret)
                return ret;
 
+       page = sg_page(so->obj->pages->sgl);
+       d = kmap(page);
+
        while (i < rodata->batch_items) {
                u32 s = rodata->batch[i];
 
-               if (reloc_index < rodata->reloc_items &&
-                   i * 4  == rodata->reloc[reloc_index]) {
-
-                       s += goffset & 0xffffffff;
-
-                       /* We keep batch offsets max 32bit */
-                       if (gen >= 8) {
+               if (i * 4  == rodata->reloc[reloc_index]) {
+                       u64 r = s + so->ggtt_offset;
+                       s = lower_32_bits(r);
+                       if (so->gen >= 8) {
                                if (i + 1 >= rodata->batch_items ||
                                    rodata->batch[i + 1] != 0)
                                        return -EINVAL;
 
-                               d[i] = s;
-                               i++;
-                               s = (goffset & 0xffffffff00000000ull) >> 32;
+                               d[i++] = s;
+                               s = upper_32_bits(r);
                        }
 
                        reloc_index++;
                }
 
-               d[i] = s;
-               i++;
+               d[i++] = s;
        }
+       kunmap(page);
 
        ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
        if (ret)
                return ret;
 
-       if (rodata->reloc_items != reloc_index) {
-               DRM_ERROR("not all relocs resolved, %d out of %d\n",
-                         reloc_index, rodata->reloc_items);
+       if (rodata->reloc[reloc_index] != -1) {
+               DRM_ERROR("only %d relocs resolved\n", reloc_index);
                return -EINVAL;
        }
 
-       so->len = rodata->batch_items * 4;
-
        return 0;
 }
 
-int i915_gem_render_state_init(struct intel_engine_cs *ring)
+void i915_gem_render_state_fini(struct render_state *so)
+{
+       i915_gem_object_ggtt_unpin(so->obj);
+       drm_gem_object_unreference(&so->obj->base);
+}
+
+int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
+                                 struct render_state *so)
 {
-       const int gen = INTEL_INFO(ring->dev)->gen;
-       struct i915_render_state *so;
-       const struct intel_renderstate_rodata *rodata;
        int ret;
 
        if (WARN_ON(ring->id != RCS))
                return -ENOENT;
 
-       rodata = render_state_get_rodata(ring->dev, gen);
-       if (rodata == NULL)
+       ret = render_state_init(so, ring->dev);
+       if (ret)
+               return ret;
+
+       if (so->rodata == NULL)
                return 0;
 
-       so = render_state_alloc(ring->dev);
-       if (IS_ERR(so))
-               return PTR_ERR(so);
+       ret = render_state_setup(so);
+       if (ret) {
+               i915_gem_render_state_fini(so);
+               return ret;
+       }
+
+       return 0;
+}
+
+int i915_gem_render_state_init(struct intel_engine_cs *ring)
+{
+       struct render_state so;
+       int ret;
 
-       ret = render_state_setup(gen, rodata, so);
+       ret = i915_gem_render_state_prepare(ring, &so);
        if (ret)
-               goto out;
+               return ret;
+
+       if (so.rodata == NULL)
+               return 0;
 
        ret = ring->dispatch_execbuffer(ring,
-                                       i915_gem_obj_ggtt_offset(so->obj),
-                                       so->len,
+                                       so.ggtt_offset,
+                                       so.rodata->batch_items * 4,
                                        I915_DISPATCH_SECURE);
        if (ret)
                goto out;
 
-       i915_vma_move_to_active(i915_gem_obj_to_ggtt(so->obj), ring);
+       i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring);
 
-       ret = __i915_add_request(ring, NULL, so->obj, NULL);
+       ret = __i915_add_request(ring, NULL, so.obj, NULL);
        /* __i915_add_request moves object to inactive if it fails */
 out:
-       render_state_free(so);
+       i915_gem_render_state_fini(&so);
        return ret;
 }