diff options
author | Alan Cox <alan@linux.intel.com> | 2011-07-15 12:32:13 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-07-15 13:05:06 -0400 |
commit | bd7b9f91ddc2d08381a853bd33b3ce7d0012b1df (patch) | |
tree | 59eeafe297d904397a3ce11bdc002874e4f921dc /drivers/staging | |
parent | c5c44531ad00ed87078e799f0932c220031aa1c9 (diff) |
gma500: Move the 2D operations into DRM
We currently have a test hack framebuffer mode ioctl, turn that into a DRM
interface.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/gma500/accel_2d.c | 60 | ||||
-rw-r--r-- | drivers/staging/gma500/framebuffer.c | 25 | ||||
-rw-r--r-- | drivers/staging/gma500/psb_drm.h | 13 | ||||
-rw-r--r-- | drivers/staging/gma500/psb_drv.c | 9 | ||||
-rw-r--r-- | drivers/staging/gma500/psb_drv.h | 7 |
5 files changed, 82 insertions, 32 deletions
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c index c719017e9db3..14400fcfe8a7 100644 --- a/drivers/staging/gma500/accel_2d.c +++ b/drivers/staging/gma500/accel_2d.c | |||
@@ -105,19 +105,20 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv, | |||
105 | * Issue one or more 2D commands to the accelerator. This needs to be | 105 | * Issue one or more 2D commands to the accelerator. This needs to be |
106 | * serialized later when we add the GEM interfaces for acceleration | 106 | * serialized later when we add the GEM interfaces for acceleration |
107 | */ | 107 | */ |
108 | int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, | 108 | static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, |
109 | unsigned size) | 109 | unsigned size) |
110 | { | 110 | { |
111 | int ret = 0; | 111 | int ret = 0; |
112 | int i; | 112 | int i; |
113 | unsigned submit_size; | 113 | unsigned submit_size; |
114 | 114 | ||
115 | mutex_lock(&dev_priv->mutex_2d); | ||
115 | while (size > 0) { | 116 | while (size > 0) { |
116 | submit_size = (size < 0x60) ? size : 0x60; | 117 | submit_size = (size < 0x60) ? size : 0x60; |
117 | size -= submit_size; | 118 | size -= submit_size; |
118 | ret = psb_2d_wait_available(dev_priv, submit_size); | 119 | ret = psb_2d_wait_available(dev_priv, submit_size); |
119 | if (ret) | 120 | if (ret) |
120 | return ret; | 121 | break; |
121 | 122 | ||
122 | submit_size <<= 2; | 123 | submit_size <<= 2; |
123 | 124 | ||
@@ -126,7 +127,8 @@ int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, | |||
126 | 127 | ||
127 | (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); | 128 | (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); |
128 | } | 129 | } |
129 | return 0; | 130 | mutex_unlock(&dev_priv->mutex_2d); |
131 | return ret; | ||
130 | } | 132 | } |
131 | 133 | ||
132 | 134 | ||
@@ -326,6 +328,7 @@ int psbfb_sync(struct fb_info *info) | |||
326 | unsigned long _end = jiffies + DRM_HZ; | 328 | unsigned long _end = jiffies + DRM_HZ; |
327 | int busy = 0; | 329 | int busy = 0; |
328 | 330 | ||
331 | mutex_lock(&dev_priv->mutex_2d); | ||
329 | /* | 332 | /* |
330 | * First idle the 2D engine. | 333 | * First idle the 2D engine. |
331 | */ | 334 | */ |
@@ -354,5 +357,56 @@ int psbfb_sync(struct fb_info *info) | |||
354 | _PSB_C2B_STATUS_BUSY) != 0); | 357 | _PSB_C2B_STATUS_BUSY) != 0); |
355 | 358 | ||
356 | out: | 359 | out: |
360 | mutex_unlock(&dev_priv->mutex_2d); | ||
357 | return (busy) ? -EBUSY : 0; | 361 | return (busy) ? -EBUSY : 0; |
358 | } | 362 | } |
363 | |||
364 | int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | ||
365 | { | ||
366 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
367 | struct drm_psb_2d_op *op = data; | ||
368 | u32 *op_ptr = &op->cmd[0]; | ||
369 | int i; | ||
370 | struct drm_gem_object *obj; | ||
371 | struct gtt_range *gtt; | ||
372 | int err = -EINVAL; | ||
373 | |||
374 | if (!dev_priv->ops->accel_2d) | ||
375 | return -EOPNOTSUPP; | ||
376 | if (op->size > PSB_2D_OP_BUFLEN) | ||
377 | return -EINVAL; | ||
378 | |||
379 | /* The GEM object being used. We need to support separate src/dst/etc | ||
380 | in the end but for now keep them all the same */ | ||
381 | obj = drm_gem_object_lookup(dev, file, op->src); | ||
382 | if (obj == NULL) | ||
383 | return -ENOENT; | ||
384 | gtt = container_of(obj, struct gtt_range, gem); | ||
385 | |||
386 | if (psb_gtt_pin(gtt) < 0) | ||
387 | goto bad_2; | ||
388 | for (i = 0; i < op->size; i++, op_ptr++) { | ||
389 | u32 r = *op_ptr & 0xF0000000; | ||
390 | /* Fill in the GTT offsets for the command buffer */ | ||
391 | if (r == PSB_2D_SRC_SURF_BH || | ||
392 | r == PSB_2D_DST_SURF_BH || | ||
393 | r == PSB_2D_MASK_SURF_BH || | ||
394 | r == PSB_2D_PAT_SURF_BH) { | ||
395 | i++; | ||
396 | op_ptr++; | ||
397 | if (i == op->size) | ||
398 | goto bad; | ||
399 | if (*op_ptr) | ||
400 | goto bad; | ||
401 | *op_ptr = gtt->offset; | ||
402 | continue; | ||
403 | } | ||
404 | } | ||
405 | psbfb_2d_submit(dev_priv, op->cmd, op->size); | ||
406 | err = 0; | ||
407 | bad: | ||
408 | psb_gtt_unpin(gtt); | ||
409 | bad_2: | ||
410 | drm_gem_object_unreference(obj); | ||
411 | return err; | ||
412 | } | ||
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c index 76b986f4180d..d890a5091cd2 100644 --- a/drivers/staging/gma500/framebuffer.c +++ b/drivers/staging/gma500/framebuffer.c | |||
@@ -200,30 +200,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
200 | static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, | 200 | static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, |
201 | unsigned long arg) | 201 | unsigned long arg) |
202 | { | 202 | { |
203 | struct psb_fbdev *fbdev = info->par; | 203 | return -ENOTTY; |
204 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
205 | struct drm_device *dev = psbfb->base.dev; | ||
206 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
207 | u32 __user *p = (u32 __user *)arg; | ||
208 | u32 l; | ||
209 | u32 buf[32]; | ||
210 | switch (cmd) { | ||
211 | case 0x12345678: | ||
212 | if (!capable(CAP_SYS_RAWIO)) | ||
213 | return -EPERM; | ||
214 | if (!dev_priv->ops->accel_2d) | ||
215 | return -EOPNOTSUPP; | ||
216 | if (get_user(l, p)) | ||
217 | return -EFAULT; | ||
218 | if (l > 32) | ||
219 | return -EMSGSIZE; | ||
220 | if (copy_from_user(buf, p + 1, l * sizeof(u32))) | ||
221 | return -EFAULT; | ||
222 | psbfb_2d_submit(dev_priv, buf, l); | ||
223 | return 0; | ||
224 | default: | ||
225 | return -ENOTTY; | ||
226 | } | ||
227 | } | 204 | } |
228 | 205 | ||
229 | static struct fb_ops psbfb_ops = { | 206 | static struct fb_ops psbfb_ops = { |
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h index 717511714318..eef53f3e6a85 100644 --- a/drivers/staging/gma500/psb_drm.h +++ b/drivers/staging/gma500/psb_drm.h | |||
@@ -161,6 +161,7 @@ struct drm_psb_register_rw_arg { | |||
161 | */ | 161 | */ |
162 | 162 | ||
163 | #define DRM_PSB_GEM_CREATE 0x10 | 163 | #define DRM_PSB_GEM_CREATE 0x10 |
164 | #define DRM_PSB_2D_OP 0x11 | ||
164 | #define DRM_PSB_DPST 0x1B | 165 | #define DRM_PSB_DPST 0x1B |
165 | #define DRM_PSB_GAMMA 0x1C | 166 | #define DRM_PSB_GAMMA 0x1C |
166 | #define DRM_PSB_DPST_BL 0x1D | 167 | #define DRM_PSB_DPST_BL 0x1D |
@@ -190,4 +191,16 @@ struct drm_psb_gem_create { | |||
190 | __u32 pad; | 191 | __u32 pad; |
191 | }; | 192 | }; |
192 | 193 | ||
194 | #define PSB_2D_OP_BUFLEN 16 | ||
195 | |||
196 | struct drm_psb_2d_op { | ||
197 | __u32 src; /* Handles, only src supported right now */ | ||
198 | __u32 dst; | ||
199 | __u32 mask; | ||
200 | __u32 pat; | ||
201 | __u32 size; /* In dwords of command */ | ||
202 | __u32 spare; /* And bumps array to u64 align */ | ||
203 | __u32 cmd[PSB_2D_OP_BUFLEN]; | ||
204 | }; | ||
205 | |||
193 | #endif | 206 | #endif |
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c index a75397711ff7..36bb716a934a 100644 --- a/drivers/staging/gma500/psb_drv.c +++ b/drivers/staging/gma500/psb_drv.c | |||
@@ -124,6 +124,9 @@ MODULE_DEVICE_TABLE(pci, pciidlist); | |||
124 | #define DRM_IOCTL_PSB_GEM_CREATE \ | 124 | #define DRM_IOCTL_PSB_GEM_CREATE \ |
125 | DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \ | 125 | DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \ |
126 | struct drm_psb_gem_create) | 126 | struct drm_psb_gem_create) |
127 | #define DRM_IOCTL_PSB_2D_OP \ | ||
128 | DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \ | ||
129 | struct drm_psb_2d_op) | ||
127 | 130 | ||
128 | static int psb_sizes_ioctl(struct drm_device *dev, void *data, | 131 | static int psb_sizes_ioctl(struct drm_device *dev, void *data, |
129 | struct drm_file *file_priv); | 132 | struct drm_file *file_priv); |
@@ -164,7 +167,7 @@ static struct drm_ioctl_desc psb_ioctls[] = { | |||
164 | psb_intel_get_pipe_from_crtc_id, 0), | 167 | psb_intel_get_pipe_from_crtc_id, 0), |
165 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl, | 168 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl, |
166 | DRM_UNLOCKED | DRM_AUTH), | 169 | DRM_UNLOCKED | DRM_AUTH), |
167 | 170 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, DRM_UNLOCKED), | |
168 | }; | 171 | }; |
169 | 172 | ||
170 | static void psb_lastclose(struct drm_device *dev) | 173 | static void psb_lastclose(struct drm_device *dev) |
@@ -179,8 +182,7 @@ static void psb_do_takedown(struct drm_device *dev) | |||
179 | 182 | ||
180 | static int psb_do_init(struct drm_device *dev) | 183 | static int psb_do_init(struct drm_device *dev) |
181 | { | 184 | { |
182 | struct drm_psb_private *dev_priv = | 185 | struct drm_psb_private *dev_priv = dev->dev_private; |
183 | (struct drm_psb_private *) dev->dev_private; | ||
184 | struct psb_gtt *pg = &dev_priv->gtt; | 186 | struct psb_gtt *pg = &dev_priv->gtt; |
185 | 187 | ||
186 | uint32_t stolen_gtt; | 188 | uint32_t stolen_gtt; |
@@ -221,6 +223,7 @@ static int psb_do_init(struct drm_device *dev) | |||
221 | 223 | ||
222 | 224 | ||
223 | spin_lock_init(&dev_priv->irqmask_lock); | 225 | spin_lock_init(&dev_priv->irqmask_lock); |
226 | mutex_init(&dev_priv->mutex_2d); | ||
224 | 227 | ||
225 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); | 228 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); |
226 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); | 229 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); |
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h index 12d13aed39db..db3e356d2860 100644 --- a/drivers/staging/gma500/psb_drv.h +++ b/drivers/staging/gma500/psb_drv.h | |||
@@ -599,6 +599,9 @@ struct drm_psb_private { | |||
599 | bool dsr_enable; | 599 | bool dsr_enable; |
600 | void (*exit_idle)(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only); | 600 | void (*exit_idle)(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only); |
601 | 601 | ||
602 | /* 2D acceleration */ | ||
603 | struct mutex mutex_2d; | ||
604 | |||
602 | /* FIXME: Arrays anyone ? */ | 605 | /* FIXME: Arrays anyone ? */ |
603 | struct mdfld_dsi_encoder *encoder0; | 606 | struct mdfld_dsi_encoder *encoder0; |
604 | struct mdfld_dsi_encoder *encoder2; | 607 | struct mdfld_dsi_encoder *encoder2; |
@@ -744,8 +747,8 @@ extern void psbfb_copyarea(struct fb_info *info, | |||
744 | const struct fb_copyarea *region); | 747 | const struct fb_copyarea *region); |
745 | extern int psbfb_sync(struct fb_info *info); | 748 | extern int psbfb_sync(struct fb_info *info); |
746 | extern void psb_spank(struct drm_psb_private *dev_priv); | 749 | extern void psb_spank(struct drm_psb_private *dev_priv); |
747 | extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, | 750 | extern int psb_accel_ioctl(struct drm_device *dev, void *data, |
748 | unsigned size); | 751 | struct drm_file *file); |
749 | 752 | ||
750 | /* | 753 | /* |
751 | * psb_reset.c | 754 | * psb_reset.c |