mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
c5c44531ad
commit
bd7b9f91dd
|
@ -105,19 +105,20 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
|
|||
* Issue one or more 2D commands to the accelerator. This needs to be
|
||||
* serialized later when we add the GEM interfaces for acceleration
|
||||
*/
|
||||
int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
|
||||
static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
|
||||
unsigned size)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
unsigned submit_size;
|
||||
|
||||
mutex_lock(&dev_priv->mutex_2d);
|
||||
while (size > 0) {
|
||||
submit_size = (size < 0x60) ? size : 0x60;
|
||||
size -= submit_size;
|
||||
ret = psb_2d_wait_available(dev_priv, submit_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
submit_size <<= 2;
|
||||
|
||||
|
@ -126,7 +127,8 @@ int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
|
|||
|
||||
(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
|
||||
}
|
||||
return 0;
|
||||
mutex_unlock(&dev_priv->mutex_2d);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -326,6 +328,7 @@ int psbfb_sync(struct fb_info *info)
|
|||
unsigned long _end = jiffies + DRM_HZ;
|
||||
int busy = 0;
|
||||
|
||||
mutex_lock(&dev_priv->mutex_2d);
|
||||
/*
|
||||
* First idle the 2D engine.
|
||||
*/
|
||||
|
@ -354,5 +357,56 @@ int psbfb_sync(struct fb_info *info)
|
|||
_PSB_C2B_STATUS_BUSY) != 0);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev_priv->mutex_2d);
|
||||
return (busy) ? -EBUSY : 0;
|
||||
}
|
||||
|
||||
int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct drm_psb_2d_op *op = data;
|
||||
u32 *op_ptr = &op->cmd[0];
|
||||
int i;
|
||||
struct drm_gem_object *obj;
|
||||
struct gtt_range *gtt;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (!dev_priv->ops->accel_2d)
|
||||
return -EOPNOTSUPP;
|
||||
if (op->size > PSB_2D_OP_BUFLEN)
|
||||
return -EINVAL;
|
||||
|
||||
/* The GEM object being used. We need to support separate src/dst/etc
|
||||
in the end but for now keep them all the same */
|
||||
obj = drm_gem_object_lookup(dev, file, op->src);
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
gtt = container_of(obj, struct gtt_range, gem);
|
||||
|
||||
if (psb_gtt_pin(gtt) < 0)
|
||||
goto bad_2;
|
||||
for (i = 0; i < op->size; i++, op_ptr++) {
|
||||
u32 r = *op_ptr & 0xF0000000;
|
||||
/* Fill in the GTT offsets for the command buffer */
|
||||
if (r == PSB_2D_SRC_SURF_BH ||
|
||||
r == PSB_2D_DST_SURF_BH ||
|
||||
r == PSB_2D_MASK_SURF_BH ||
|
||||
r == PSB_2D_PAT_SURF_BH) {
|
||||
i++;
|
||||
op_ptr++;
|
||||
if (i == op->size)
|
||||
goto bad;
|
||||
if (*op_ptr)
|
||||
goto bad;
|
||||
*op_ptr = gtt->offset;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
psbfb_2d_submit(dev_priv, op->cmd, op->size);
|
||||
err = 0;
|
||||
bad:
|
||||
psb_gtt_unpin(gtt);
|
||||
bad_2:
|
||||
drm_gem_object_unreference(obj);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -200,30 +200,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
|||
static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct psb_fbdev *fbdev = info->par;
|
||||
struct psb_framebuffer *psbfb = &fbdev->pfb;
|
||||
struct drm_device *dev = psbfb->base.dev;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
u32 __user *p = (u32 __user *)arg;
|
||||
u32 l;
|
||||
u32 buf[32];
|
||||
switch (cmd) {
|
||||
case 0x12345678:
|
||||
if (!capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
if (!dev_priv->ops->accel_2d)
|
||||
return -EOPNOTSUPP;
|
||||
if (get_user(l, p))
|
||||
return -EFAULT;
|
||||
if (l > 32)
|
||||
return -EMSGSIZE;
|
||||
if (copy_from_user(buf, p + 1, l * sizeof(u32)))
|
||||
return -EFAULT;
|
||||
psbfb_2d_submit(dev_priv, buf, l);
|
||||
return 0;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static struct fb_ops psbfb_ops = {
|
||||
|
|
|
@ -161,6 +161,7 @@ struct drm_psb_register_rw_arg {
|
|||
*/
|
||||
|
||||
#define DRM_PSB_GEM_CREATE 0x10
|
||||
#define DRM_PSB_2D_OP 0x11
|
||||
#define DRM_PSB_DPST 0x1B
|
||||
#define DRM_PSB_GAMMA 0x1C
|
||||
#define DRM_PSB_DPST_BL 0x1D
|
||||
|
@ -190,4 +191,16 @@ struct drm_psb_gem_create {
|
|||
__u32 pad;
|
||||
};
|
||||
|
||||
#define PSB_2D_OP_BUFLEN 16
|
||||
|
||||
struct drm_psb_2d_op {
|
||||
__u32 src; /* Handles, only src supported right now */
|
||||
__u32 dst;
|
||||
__u32 mask;
|
||||
__u32 pat;
|
||||
__u32 size; /* In dwords of command */
|
||||
__u32 spare; /* And bumps array to u64 align */
|
||||
__u32 cmd[PSB_2D_OP_BUFLEN];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -124,6 +124,9 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
|
|||
#define DRM_IOCTL_PSB_GEM_CREATE \
|
||||
DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_gem_create)
|
||||
#define DRM_IOCTL_PSB_2D_OP \
|
||||
DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_2d_op)
|
||||
|
||||
static int psb_sizes_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
@ -164,7 +167,7 @@ static struct drm_ioctl_desc psb_ioctls[] = {
|
|||
psb_intel_get_pipe_from_crtc_id, 0),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
|
||||
DRM_UNLOCKED | DRM_AUTH),
|
||||
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, DRM_UNLOCKED),
|
||||
};
|
||||
|
||||
static void psb_lastclose(struct drm_device *dev)
|
||||
|
@ -179,8 +182,7 @@ static void psb_do_takedown(struct drm_device *dev)
|
|||
|
||||
static int psb_do_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv =
|
||||
(struct drm_psb_private *) dev->dev_private;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct psb_gtt *pg = &dev_priv->gtt;
|
||||
|
||||
uint32_t stolen_gtt;
|
||||
|
@ -221,6 +223,7 @@ static int psb_do_init(struct drm_device *dev)
|
|||
|
||||
|
||||
spin_lock_init(&dev_priv->irqmask_lock);
|
||||
mutex_init(&dev_priv->mutex_2d);
|
||||
|
||||
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
|
||||
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
|
||||
|
|
|
@ -599,6 +599,9 @@ struct drm_psb_private {
|
|||
bool dsr_enable;
|
||||
void (*exit_idle)(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only);
|
||||
|
||||
/* 2D acceleration */
|
||||
struct mutex mutex_2d;
|
||||
|
||||
/* FIXME: Arrays anyone ? */
|
||||
struct mdfld_dsi_encoder *encoder0;
|
||||
struct mdfld_dsi_encoder *encoder2;
|
||||
|
@ -744,8 +747,8 @@ extern void psbfb_copyarea(struct fb_info *info,
|
|||
const struct fb_copyarea *region);
|
||||
extern int psbfb_sync(struct fb_info *info);
|
||||
extern void psb_spank(struct drm_psb_private *dev_priv);
|
||||
extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
|
||||
unsigned size);
|
||||
extern int psb_accel_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
|
||||
/*
|
||||
* psb_reset.c
|
||||
|
|
Loading…
Reference in New Issue