Example #1
0
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;
}
Example #2
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;
}
Example #4
0
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;
}
Example #5
0
/**
 * @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;
}
Example #6
0
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;
}
Example #8
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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
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");
}
Example #13
0
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;
}