diff options
Diffstat (limited to 'drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c')
-rw-r--r-- | drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c index 6ae4d6e..ed14901 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c @@ -38,8 +38,14 @@ #include "fimg2d_clk.h" #include "fimg2d_ctx.h" #include "fimg2d_helper.h" +#include "fimg2d_cache.h" #define CTX_TIMEOUT msecs_to_jiffies(1000) +#define LV1_SHIFT 20 +#define LV2_BASE_MASK 0x3ff +#define LV2_PT_MASK 0xff000 +#define LV2_SHIFT 12 +#define LV1_DESC_MASK 0x3 static struct fimg2d_control *info; @@ -58,7 +64,13 @@ static DECLARE_WORK(fimg2d_work, fimg2d_worker); static irqreturn_t fimg2d_irq(int irq, void *dev_id) { fimg2d_debug("irq\n"); - info->stop(info); + if (!atomic_read(&info->clkon)) { + fimg2d_clk_on(info); + info->stop(info); + fimg2d_clk_off(info); + } else { + info->stop(info); + } return IRQ_HANDLED; } @@ -67,6 +79,8 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype, unsigned long pgtable_base, unsigned long fault_addr) { struct fimg2d_bltcmd *cmd; + unsigned long *pgd; + unsigned long *lv1d, *lv2d; if (itype == SYSMMU_PAGEFAULT) { printk(KERN_ERR "[%s] sysmmu page fault(0x%lx), pgd(0x%lx)\n", @@ -91,11 +105,20 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype, fimg2d_dump_command(cmd); + pgd = (unsigned long *)cmd->ctx->mm->pgd; + lv1d = pgd + (fault_addr >> LV1_SHIFT); + printk(KERN_ERR " Level 1 descriptor(0x%lx)\n", *lv1d); + if ((*lv1d & LV1_DESC_MASK) != 0x1) { + fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4); + goto next; + } + + lv2d = (unsigned long *)phys_to_virt(*lv1d & ~LV2_BASE_MASK) + + ((fault_addr & LV2_PT_MASK) >> LV2_SHIFT); + printk(KERN_ERR " Level 2 descriptor(0x%lx)\n", *lv2d); + fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4); next: - fimg2d_clk_dump(info); - info->dump(info); - BUG(); return 0; } @@ -106,8 +129,6 @@ static void fimg2d_context_wait(struct fimg2d_context *ctx) atomic_set(&info->active, 1); queue_work(info->work_q, &fimg2d_work); printk(KERN_ERR "[%s] ctx %p cmd wait timeout\n", __func__, ctx); - if (info->err) - break; } } } @@ -188,11 +209,8 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case FIMG2D_BITBLT_BLIT: - if (info->err) { - printk(KERN_ERR "[%s] device error, do sw fallback\n", - __func__); + if (info->secure) return -EFAULT; - } if (copy_from_user(&blit, (void *)arg, sizeof(blit))) return -EFAULT; @@ -245,6 +263,24 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EFAULT; break; + case FIMG2D_BITBLT_SECURE: + if (copy_from_user(&info->secure, + (unsigned int *)arg, + sizeof(unsigned int))) { + printk(KERN_ERR + "[%s] failed to FIMG2D_BITBLT_SECURE: copy_from_user error\n\n", + __func__); + return -EFAULT; + } + + while (1) { + if (fimg2d_queue_is_empty(&info->cmd_q)) + break; + mdelay(2); + } + + break; + default: printk(KERN_ERR "[%s] unknown ioctl\n", __func__); ret = -EFAULT; @@ -278,6 +314,7 @@ static int fimg2d_setup_controller(struct fimg2d_control *info) atomic_set(&info->busy, 0); atomic_set(&info->nctx, 0); atomic_set(&info->active, 0); + info->secure = 0; spin_lock_init(&info->bltlock); |