static int fimg2d_remove(struct platform_device *pdev) { #ifdef CONFIG_ARM_EXYNOS_IKS_CPUFREQ pm_qos_remove_request(&exynos5_g2d_cpu_qos); pm_qos_remove_request(&exynos5_g2d_mif_qos); #endif misc_deregister(&fimg2d_dev); #ifdef CONFIG_PM_RUNTIME pm_runtime_disable(&pdev->dev); #else fimg2d_clk_off(ctrl); #endif fimg2d_clk_release(ctrl); free_irq(ctrl->irq, NULL); if (ctrl->mem) { iounmap(ctrl->regs); release_resource(ctrl->mem); kfree(ctrl->mem); } #ifdef BLIT_WORKQUE destroy_workqueue(ctrl->work_q); #endif mutex_destroy(&ctrl->drvlock); kfree(ctrl); return 0; }
static int fimg2d_remove(struct platform_device *pdev) { struct fimg2d_platdata *pdata; #ifdef CONFIG_OF pdata = ctrl->pdata; #else pdata = to_fimg2d_plat(ctrl->dev); #endif fimg2d_pm_qos_remove(ctrl); misc_deregister(&fimg2d_dev); #ifdef CONFIG_PM_RUNTIME pm_runtime_disable(&pdev->dev); #else fimg2d_clk_off(ctrl); #endif fimg2d_clk_release(ctrl); free_irq(ctrl->irq, NULL); if (ctrl->mem) { iounmap(ctrl->regs); release_resource(ctrl->mem); kfree(ctrl->mem); } #ifdef BLIT_WORKQUE destroy_workqueue(ctrl->work_q); #endif mutex_destroy(&ctrl->drvlock); kfree(ctrl); kfree(pdata); return 0; }
static int fimg2d_do_bitblt(struct fimg2d_control *ctrl) { int ret; if (fimg2d_ip_version_is() >= IP_VER_G2D_5AR) { pm_runtime_get_sync(ctrl->dev); fimg2d_debug("Done pm_runtime_get_sync()\n"); } else { pm_runtime_get_sync(ctrl->dev); fimg2d_debug("Done pm_runtime_get_sync()\n"); } fimg2d_clk_on(ctrl); ret = ctrl->blit(ctrl); fimg2d_clk_off(ctrl); if (fimg2d_ip_version_is() >= IP_VER_G2D_5AR) { pm_runtime_put_sync(ctrl->dev); fimg2d_debug("Done pm_runtime_put_sync()\n"); } else { pm_runtime_put_sync(ctrl->dev); fimg2d_debug("Done pm_runtime_put_sync()\n"); } return ret; }
static int fimg2d_do_bitblt(struct fimg2d_control *ctrl) { int ret; fimg2d_clk_on(ctrl); ret = ctrl->blit(ctrl); fimg2d_clk_off(ctrl); return ret; }
/** * @irq: irq number * @dev_id: pointer to private data */ static irqreturn_t fimg2d_irq(int irq, void *dev_id) { fimg2d_debug("irq\n"); if (!atomic_read(&info->clkon)) { fimg2d_clk_on(info); info->stop(info); fimg2d_clk_off(info); } else { info->stop(info); } return IRQ_HANDLED; }
static int fimg2d_do_bitblt(struct fimg2d_control *ctrl) { int ret; pm_runtime_get_sync(ctrl->dev); fimg2d_debug("Done pm_runtime_get_sync()\n"); fimg2d_clk_on(ctrl); ret = ctrl->blit(ctrl); fimg2d_clk_off(ctrl); pm_runtime_put_sync(ctrl->dev); fimg2d_debug("Done pm_runtime_put_sync()\n"); return ret; }
static int fimg2d_resume(struct device *dev) { unsigned long flags; g2d_lock(&ctrl->drvlock); g2d_spin_lock(&ctrl->bltlock, flags); atomic_set(&ctrl->suspended, 0); g2d_spin_unlock(&ctrl->bltlock, flags); g2d_unlock(&ctrl->drvlock); /* G2D clk gating mask */ if (ip_is_g2d_5ar2()) { fimg2d_clk_on(ctrl); fimg2d_clk_off(ctrl); } fimg2d_info("resume... done\n"); return 0; }
static int fimg2d_do_bitblt(struct fimg2d_control *ctrl) { int ret; #ifdef CONFIG_PM_RUNTIME pm_runtime_get_sync(ctrl->dev); fimg2d_debug("pm_runtime_get_sync\n"); fimg2d_clk_on(ctrl); #endif ret = ctrl->blit(ctrl); #ifdef CONFIG_PM_RUNTIME fimg2d_clk_off(ctrl); pm_runtime_put_sync(ctrl->dev); fimg2d_debug("pm_runtime_put_sync\n"); #endif return ret; }
static int fimg2d_resume(struct device *dev) { unsigned long flags; int ret = 0; g2d_spin_lock(&ctrl->bltlock, flags); atomic_set(&ctrl->suspended, 0); g2d_spin_unlock(&ctrl->bltlock, flags); /* G2D clk gating mask */ if (ip_is_g2d_5ar2()) { fimg2d_clk_on(ctrl); fimg2d_clk_off(ctrl); } else if (ip_is_g2d_5hp()) { ret = exynos5430_fimg2d_clk_set(ctrl); if (ret) { fimg2d_err("failed to exynos5430_fimg2d_clk_set()\n"); return -ENOENT; } } fimg2d_info("resume... done\n"); return ret; }
static int fimg2d_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; if (!to_fimg2d_plat(&pdev->dev)) { fimg2d_err("failed to get platform data\n"); return -ENOMEM; } /* global structure */ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { fimg2d_err("failed to allocate memory for controller\n"); return -ENOMEM; } /* setup global ctrl */ ret = fimg2d_setup_controller(ctrl); if (ret) { fimg2d_err("failed to setup controller\n"); goto drv_free; } ctrl->dev = &pdev->dev; /* memory region */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { fimg2d_err("failed to get resource\n"); ret = -ENOENT; goto drv_free; } ctrl->mem = request_mem_region(res->start, resource_size(res), pdev->name); if (!ctrl->mem) { fimg2d_err("failed to request memory region\n"); ret = -ENOMEM; goto res_free; } /* ioremap */ ctrl->regs = ioremap(res->start, resource_size(res)); if (!ctrl->regs) { fimg2d_err("failed to ioremap for SFR\n"); ret = -ENOENT; goto mem_free; } fimg2d_info("base address: 0x%lx\n", (unsigned long)res->start); /* irq */ ctrl->irq = platform_get_irq(pdev, 0); if (!ctrl->irq) { fimg2d_err("failed to get irq resource\n"); ret = -ENOENT; goto reg_unmap; } fimg2d_info("irq: %d\n", ctrl->irq); ret = request_irq(ctrl->irq, fimg2d_irq, IRQF_DISABLED, pdev->name, ctrl); if (ret) { fimg2d_err("failed to request irq\n"); ret = -ENOENT; goto reg_unmap; } ret = fimg2d_clk_setup(ctrl); if (ret) { fimg2d_err("failed to setup clk\n"); ret = -ENOENT; goto irq_free; } #ifdef CONFIG_PM_RUNTIME pm_runtime_enable(ctrl->dev); fimg2d_info("enable runtime pm\n"); pm_runtime_get_sync(ctrl->dev); #else fimg2d_clk_on(ctrl); #endif exynos_sysmmu_set_fault_handler(ctrl->dev, fimg2d_sysmmu_fault_handler); fimg2d_info("register sysmmu page fault handler\n"); /* misc register */ ret = misc_register(&fimg2d_dev); if (ret) { fimg2d_err("failed to register misc driver\n"); goto clk_release; } #ifdef CONFIG_ARM_EXYNOS_IKS_CPUFREQ pm_qos_add_request(&exynos5_g2d_cpu_qos, PM_QOS_CPU_FREQ_MIN, 0); pm_qos_add_request(&exynos5_g2d_mif_qos, PM_QOS_BUS_THROUGHPUT, 0); #endif return 0; clk_release: #ifdef CONFIG_PM_RUNTIME pm_runtime_disable(ctrl->dev); #else fimg2d_clk_off(ctrl); #endif fimg2d_clk_release(ctrl); irq_free: free_irq(ctrl->irq, NULL); reg_unmap: iounmap(ctrl->regs); mem_free: kfree(ctrl->mem); res_free: release_resource(ctrl->mem); drv_free: #ifdef BLIT_WORKQUE if (ctrl->work_q) destroy_workqueue(ctrl->work_q); #endif mutex_destroy(&ctrl->drvlock); kfree(ctrl); return ret; }
static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; struct fimg2d_context *ctx; struct mm_struct *mm; ctx = file->private_data; switch (cmd) { case FIMG2D_BITBLT_BLIT: mm = get_task_mm(current); if(!mm) { fimg2d_err("no mm for ctx\n"); return -ENXIO; } fimg2d_clk_on(ctrl); g2d_lock(&ctrl->drvlock); ctx->mm = mm; if (atomic_read(&ctrl->drvact) || atomic_read(&ctrl->suspended)) { fimg2d_err("driver is unavailable, do sw fallback\n"); g2d_unlock(&ctrl->drvlock); fimg2d_clk_off(ctrl); mmput(mm); return -EPERM; } ret = fimg2d_add_command(ctrl, ctx, (struct fimg2d_blit __user *)arg); if (ret) { fimg2d_err("add command not allowed.\n"); g2d_unlock(&ctrl->drvlock); fimg2d_clk_off(ctrl); mmput(mm); return ret; } ret = fimg2d_request_bitblt(ctrl, ctx); if (ret) { fimg2d_err("request bitblit not allowed.\n"); g2d_unlock(&ctrl->drvlock); fimg2d_clk_off(ctrl); mmput(mm); return -EBUSY; } g2d_unlock(&ctrl->drvlock); fimg2d_clk_off(ctrl); mmput(mm); break; case FIMG2D_BITBLT_VERSION: { struct fimg2d_version ver; struct fimg2d_platdata *pdata; pdata = to_fimg2d_plat(ctrl->dev); ver.hw = pdata->hw_ver; ver.sw = 0; fimg2d_info("version info. hw(0x%x), sw(0x%x)\n", ver.hw, ver.sw); if (copy_to_user((void *)arg, &ver, sizeof(ver))) return -EFAULT; break; } case FIMG2D_BITBLT_ACTIVATE: { enum driver_act act; if (copy_from_user(&act, (void *)arg, sizeof(act))) return -EFAULT; g2d_lock(&ctrl->drvlock); atomic_set(&ctrl->drvact, act); if (act == DRV_ACT) fimg2d_info("fimg2d driver is activated\n"); else fimg2d_info("fimg2d driver is deactivated\n"); g2d_unlock(&ctrl->drvlock); break; } default: fimg2d_err("unknown ioctl\n"); ret = -EFAULT; break; } return ret; }
void fimg2d4x_bitblt(struct fimg2d_control *info) { struct fimg2d_context *ctx; struct fimg2d_bltcmd *cmd; unsigned long *pgd; fimg2d_debug("enter blitter\n"); #ifdef CONFIG_PM_RUNTIME pm_runtime_get_sync(info->dev); fimg2d_debug("pm_runtime_get_sync\n"); #endif fimg2d_clk_on(info); while ((cmd = fimg2d_get_first_command(info))) { ctx = cmd->ctx; if (info->err) { printk(KERN_ERR "[%s] device error\n", __func__); goto blitend; } atomic_set(&info->busy, 1); info->configure(info, cmd); if (cmd->image[IDST].addr.type != ADDR_PHYS) { pgd = (unsigned long *)ctx->mm->pgd; s5p_sysmmu_enable(info->dev, (unsigned long)virt_to_phys(pgd)); fimg2d_debug("sysmmu enable: pgd %p ctx %p seq_no(%u)\n", pgd, ctx, cmd->seq_no); } fimg2d4x_pre_bitblt(info, cmd); #ifdef PERF_PROFILE perf_start(cmd->ctx, PERF_BLIT); #endif /* start blit */ info->run(info); fimg2d4x_blit_wait(info, cmd); #ifdef PERF_PROFILE perf_end(cmd->ctx, PERF_BLIT); #endif if (cmd->image[IDST].addr.type != ADDR_PHYS) { s5p_sysmmu_disable(info->dev); fimg2d_debug("sysmmu disable\n"); } blitend: spin_lock(&info->bltlock); fimg2d_dequeue(&cmd->node); kfree(cmd); atomic_dec(&ctx->ncmd); /* wake up context */ if (!atomic_read(&ctx->ncmd)) wake_up(&ctx->wait_q); spin_unlock(&info->bltlock); } atomic_set(&info->active, 0); fimg2d_clk_off(info); #ifdef CONFIG_PM_RUNTIME pm_runtime_put_sync(info->dev); fimg2d_debug("pm_runtime_put_sync\n"); #endif fimg2d_debug("exit blitter\n"); }
static int fimg2d_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; struct fimg2d_platdata *pdata; #ifdef CONFIG_OF struct device *dev = &pdev->dev; int id = 0; #else pdata = to_fimg2d_plat(&pdev->dev); #endif dev_info(&pdev->dev, "++%s\n", __func__); #ifdef CONFIG_OF if (dev->of_node) { id = of_alias_get_id(pdev->dev.of_node, "fimg2d"); } else { id = pdev->id; pdata = dev->platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; } } #else if (!to_fimg2d_plat(&pdev->dev)) { fimg2d_err("failed to get platform data\n"); return -ENOMEM; } #endif /* global structure */ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { fimg2d_err("failed to allocate memory for controller\n"); return -ENOMEM; } #ifdef CONFIG_OF pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) { fimg2d_err("failed to allocate memory for controller\n"); kfree(ctrl); return -ENOMEM; } ctrl->pdata = pdata; g2d_parse_dt(dev->of_node, ctrl->pdata); #endif /* setup global ctrl */ ret = fimg2d_setup_controller(ctrl); if (ret) { fimg2d_err("failed to setup controller\n"); goto drv_free; } ctrl->dev = &pdev->dev; /* memory region */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { fimg2d_err("failed to get resource\n"); ret = -ENOENT; goto drv_free; } ctrl->mem = request_mem_region(res->start, resource_size(res), pdev->name); if (!ctrl->mem) { fimg2d_err("failed to request memory region\n"); ret = -ENOMEM; goto drv_free; } /* ioremap */ ctrl->regs = ioremap(res->start, resource_size(res)); if (!ctrl->regs) { fimg2d_err("failed to ioremap for SFR\n"); ret = -ENOENT; goto mem_free; } fimg2d_debug("base address: 0x%lx\n", (unsigned long)res->start); /* irq */ ctrl->irq = platform_get_irq(pdev, 0); if (!ctrl->irq) { fimg2d_err("failed to get irq resource\n"); ret = -ENOENT; goto reg_unmap; } fimg2d_debug("irq: %d\n", ctrl->irq); ret = request_irq(ctrl->irq, fimg2d_irq, IRQF_DISABLED, pdev->name, ctrl); if (ret) { fimg2d_err("failed to request irq\n"); ret = -ENOENT; goto reg_unmap; } ret = fimg2d_clk_setup(ctrl); if (ret) { fimg2d_err("failed to setup clk\n"); ret = -ENOENT; goto irq_free; } spin_lock_init(&ctrl->qoslock); #ifdef CONFIG_PM_RUNTIME pm_runtime_enable(ctrl->dev); fimg2d_info("enable runtime pm\n"); #else fimg2d_clk_on(ctrl); #endif #ifdef FIMG2D_IOVMM_PAGETABLE exynos_create_iovmm(dev, 3, 3); #endif iovmm_set_fault_handler(dev, fimg2d_sysmmu_fault_handler, ctrl); fimg2d_debug("register sysmmu page fault handler\n"); /* misc register */ ret = misc_register(&fimg2d_dev); if (ret) { fimg2d_err("failed to register misc driver\n"); goto clk_release; } fimg2d_pm_qos_add(ctrl); dev_info(&pdev->dev, "fimg2d registered successfully\n"); return 0; clk_release: #ifdef CONFIG_PM_RUNTIME pm_runtime_disable(ctrl->dev); #else fimg2d_clk_off(ctrl); #endif fimg2d_clk_release(ctrl); irq_free: free_irq(ctrl->irq, NULL); reg_unmap: iounmap(ctrl->regs); mem_free: release_mem_region(res->start, resource_size(res)); drv_free: #ifdef BLIT_WORKQUE if (ctrl->work_q) destroy_workqueue(ctrl->work_q); #endif mutex_destroy(&ctrl->drvlock); #ifdef CONFIG_OF kfree(pdata); #endif kfree(ctrl); return ret; }