int jpeg_mmap(struct file *filp, struct vm_area_struct *vma) { #if defined(CONFIG_S5P_SYSMMU_JPEG) #if !defined(CONFIG_S5P_VMEM) unsigned long page_frame_no; unsigned long start; unsigned long size; char *ptr; /* vmalloc */ size = vma->vm_end - vma->vm_start; ptr = (char *)jpeg_ctrl->mem.base; start = 0; vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); while (size > 0) { page_frame_no = vmalloc_to_pfn(ptr); if (remap_pfn_range(vma, vma->vm_start + start, page_frame_no, PAGE_SIZE, vma->vm_page_prot)) { jpeg_err("failed to remap jpeg pfn range.\n"); return -ENOMEM; } start += PAGE_SIZE; ptr += PAGE_SIZE; size -= PAGE_SIZE; } #endif /* CONFIG_S5P_VMEM */ #else unsigned long page_frame_no; unsigned long size; int ret; size = vma->vm_end - vma->vm_start; if (!cma_is_registered_region(jpeg_ctrl->mem.base, size)) { pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n", __func__, (unsigned int)size, jpeg_ctrl->mem.base); return -EINVAL; } vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); page_frame_no = __phys_to_pfn(jpeg_ctrl->mem.base); ret = remap_pfn_range(vma, vma->vm_start, page_frame_no, size, vma->vm_page_prot); if (ret != 0) { jpeg_err("failed to remap jpeg pfn range.\n"); return -ENOMEM; } #endif /* SYSMMU_JPEG_ON */ return 0; }
int jpeg_set_enc_param(struct jpeg_control *ctrl) { if (ctrl) { jpeg_sw_reset(ctrl->reg_base); } else { jpeg_err("jpeg ctrl is NULL\n"); return -1; } jpeg_set_clk_power_on(ctrl->reg_base); jpeg_set_mode(ctrl->reg_base, 0); jpeg_set_enc_in_fmt(ctrl->reg_base, ctrl->enc_param.in_fmt); jpeg_set_enc_out_fmt(ctrl->reg_base, ctrl->enc_param.out_fmt); jpeg_set_enc_dri(ctrl->reg_base, 2); jpeg_set_frame_size(ctrl->reg_base, ctrl->enc_param.width, ctrl->enc_param.height); jpeg_set_stream_buf(&ctrl->mem.stream_data_addr, ctrl->mem.base); jpeg_set_stream_addr(ctrl->reg_base, ctrl->mem.stream_data_addr); jpeg_set_frame_buf(&ctrl->mem.frame_data_addr, ctrl->mem.base); jpeg_set_frame_addr(ctrl->reg_base, ctrl->mem.frame_data_addr); jpeg_set_enc_coef(ctrl->reg_base); jpeg_set_enc_qtbl(ctrl->reg_base, ctrl->enc_param.quality); jpeg_set_enc_htbl(ctrl->reg_base); return 0; }
int jpeg_set_dec_param(struct jpeg_control *ctrl) { if (ctrl) { jpeg_sw_reset(ctrl->reg_base); } else { jpeg_err("jpeg ctrl is NULL\n"); return -1; } jpeg_set_clk_power_on(ctrl->reg_base); jpeg_set_mode(ctrl->reg_base, 1); jpeg_set_dec_out_fmt(ctrl->reg_base, ctrl->dec_param.out_fmt); jpeg_set_stream_buf(&ctrl->mem.stream_data_addr, ctrl->mem.base); jpeg_set_stream_addr(ctrl->reg_base, ctrl->mem.stream_data_addr); jpeg_set_frame_buf(&ctrl->mem.frame_data_addr, ctrl->mem.base); jpeg_set_frame_addr(ctrl->reg_base, ctrl->mem.frame_data_addr); jpeg_info("jpeg_set_dec_param fmt(%d)\ img_addr(0x%08x) jpeg_addr(0x%08x)\n", ctrl->dec_param.out_fmt, ctrl->mem.frame_data_addr, ctrl->mem.stream_data_addr); return 0; }
static int jpeg_m2m_open(struct file *file) { struct jpeg_dev *dev = video_drvdata(file); struct jpeg_ctx *ctx = NULL; int ret = 0; enum jpeg_node_type node; node = jpeg_get_node_type(file); if (node == JPEG_NODE_INVALID) { jpeg_err("cannot specify node type\n"); ret = -ENOENT; goto err_node_type; } ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) return -ENOMEM; file->private_data = ctx; ctx->dev = dev; spin_lock_init(&ctx->slock); if (node == JPEG_NODE_DECODER) ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, queue_init_dec); else ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_enc, ctx, queue_init_enc); if (IS_ERR(ctx->m2m_ctx)) { int err = PTR_ERR(ctx->m2m_ctx); kfree(ctx); return err; } clk_enable(dev->clk); #ifdef CONFIG_PM_RUNTIME #if defined (CONFIG_CPU_EXYNOS5250) dev->vb2->resume(dev->alloc_ctx); #ifdef CONFIG_BUSFREQ_OPP /* lock bus frequency */ dev_lock(dev->bus_dev, &dev->plat_dev->dev, BUSFREQ_400MHZ); #endif #else pm_runtime_get_sync(&dev->plat_dev->dev); #endif #endif return 0; err_node_type: kfree(ctx); return ret; }
int jpeg_exe_enc(struct jpeg_control *ctrl) { jpeg_start_encode(ctrl->reg_base); if (interruptible_sleep_on_timeout(&ctrl->wq, INT_TIMEOUT) == 0) jpeg_err("waiting for interrupt is timeout\n"); if (ctrl->irq_ret != OK_ENC_OR_DEC) { jpeg_err("jpeg encode error(%d)\n", ctrl->irq_ret); return -1; } ctrl->enc_param.size = jpeg_get_stream_size(ctrl->reg_base); return 0; }
static int jpeg_suspend(struct platform_device *pdev, pm_message_t state) { /* clock disable */ clk_disable(jpeg_ctrl->clk); #if defined(CONFIG_CPU_S5PV210) if (s5pv210_pd_disable("jpeg_pd") < 0) { jpeg_err("failed to disable jpeg power domain\n"); return -EINVAL; } #endif return 0; }
static int jpeg_resume(struct platform_device *pdev) { #if defined(CONFIG_CPU_S5PV210) if (s5pv210_pd_enable("jpeg_pd") < 0) { jpeg_err("failed to enable jpeg power domain\n"); return -EINVAL; } #endif /* clock enable */ clk_enable(jpeg_ctrl->clk); return 0; }
static int __init jpeg_hx_init(void) { int ret; printk(KERN_CRIT "Initialize JPEG Hx driver\n"); ret = platform_driver_register(&jpeg_hx_driver); if (ret) jpeg_err("failed to register jpeg hx driver\n"); return ret; }
static int jpeg_m2m_open(struct file *file) { struct jpeg_dev *dev = video_drvdata(file); struct jpeg_ctx *ctx = NULL; int ret = 0; enum jpeg_node_type node; node = jpeg_get_node_type(file); if (node == JPEG_NODE_INVALID) { jpeg_err("cannot specify node type\n"); ret = -ENOENT; goto err_node_type; } ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) return -ENOMEM; file->private_data = ctx; ctx->dev = dev; if (node == JPEG_NODE_DECODER) ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, queue_init_dec); else ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_enc, ctx, queue_init_enc); if (IS_ERR(ctx->m2m_ctx)) { int err = PTR_ERR(ctx->m2m_ctx); kfree(ctx); return err; } clk_enable(dev->clk); #ifdef CONFIG_PM_RUNTIME pm_runtime_get_sync(&dev->plat_dev->dev); #endif return 0; err_node_type: kfree(ctx); return ret; }
int jpeg_exe_dec(struct jpeg_control *ctrl) { jpeg_start_decode(ctrl->reg_base); if (interruptible_sleep_on_timeout(&ctrl->wq, INT_TIMEOUT) == 0) jpeg_err("waiting for interrupt is timeout\n"); if (ctrl->irq_ret != OK_ENC_OR_DEC) { jpeg_err("jpeg decode error(%d)\n", ctrl->irq_ret); return -1; } jpeg_get_frame_size(ctrl->reg_base, &ctrl->dec_param.width, &ctrl->dec_param.height); ctrl->dec_param.in_fmt = jpeg_get_stream_fmt(ctrl->reg_base); jpeg_info("decode img in_fmt(%d) width(%d) height(%d)\n", ctrl->dec_param.in_fmt , ctrl->dec_param.width, ctrl->dec_param.height); return 0; }
static inline enum jpeg_node_type jpeg_get_node_type(struct file *file) { struct video_device *vdev = video_devdata(file); if (!vdev) { jpeg_err("failed to get video_device\n"); return JPEG_NODE_INVALID; } jpeg_dbg("video_device index: %d\n", vdev->num); if (vdev->num == JPEG_NODE_DECODER) return JPEG_NODE_DECODER; else if (vdev->num == JPEG_NODE_ENCODER) return JPEG_NODE_ENCODER; else return JPEG_NODE_INVALID; }
static int jpeg_release(struct inode *inode, struct file *file) { atomic_dec(&jpeg_ctrl->in_use); jpeg_mem_free(); clk_disable(jpeg_ctrl->clk); #if defined(CONFIG_CPU_S5PV210) if (s5pv210_pd_disable("jpeg_pd") < 0) { jpeg_err("failed to disable jpeg power domain\n"); return -EINVAL; } #endif #ifdef CONFIG_PM_RUNTIME pm_runtime_put_sync(jpeg_pm); #endif return 0; }
static int jpeg_open(struct inode *inode, struct file *file) { int ret; int in_use; mutex_lock(&jpeg_ctrl->lock); in_use = atomic_read(&jpeg_ctrl->in_use); if (in_use > JPEG_MAX_INSTANCE) { ret = -EBUSY; goto resource_busy; } else { atomic_inc(&jpeg_ctrl->in_use); jpeg_info("jpeg driver opened.\n"); } mutex_unlock(&jpeg_ctrl->lock); #if defined(CONFIG_CPU_S5PV210) ret = s5pv210_pd_enable("jpeg_pd"); if (ret < 0) { jpeg_err("failed to enable jpeg power domain\n"); return -EINVAL; } #endif /* clock enable */ clk_enable(jpeg_ctrl->clk); file->private_data = (struct jpeg_control *)jpeg_ctrl; #ifdef CONFIG_PM_RUNTIME pm_runtime_get_sync(jpeg_pm); #endif return 0; resource_busy: mutex_unlock(&jpeg_ctrl->lock); return ret; }
static int jpeg_probe(struct platform_device *pdev) { struct jpeg_dev *dev; struct video_device *vfd; struct resource *res; int ret; /* global structure */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { dev_err(&pdev->dev, "%s: not enough memory\n", __func__); ret = -ENOMEM; goto err_alloc; } dev->plat_dev = pdev; /* setup jpeg control */ ret = jpeg_setup_controller(dev); if (ret) { jpeg_err("failed to setup controller\n"); goto err_setup; } /* memory region */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { jpeg_err("failed to get jpeg memory region resource\n"); ret = -ENOENT; goto err_res; } res = request_mem_region(res->start, resource_size(res), pdev->name); if (!res) { jpeg_err("failed to request jpeg io memory region\n"); ret = -ENOMEM; goto err_region; } /* ioremap */ dev->reg_base = ioremap(res->start, resource_size(res)); if (!dev->reg_base) { jpeg_err("failed to remap jpeg io region\n"); ret = -ENOENT; goto err_map; } spin_lock_init(&dev->slock); /* irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { jpeg_err("failed to request jpeg irq resource\n"); ret = -ENOENT; goto err_irq; } dev->irq_no = res->start; ret = request_irq(dev->irq_no, (void *)jpeg_irq, IRQF_DISABLED, pdev->name, dev); if (ret != 0) { jpeg_err("failed to jpeg request irq\n"); ret = -ENOENT; goto err_irq; } /* clock */ dev->clk = clk_get(&pdev->dev, "jpeg"); if (IS_ERR(dev->clk)) { jpeg_err("failed to find jpeg clock source\n"); ret = -ENOENT; goto err_clk; } #ifdef CONFIG_PM_RUNTIME pm_runtime_enable(&pdev->dev); #endif /* clock enable */ clk_enable(dev->clk); ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register v4l2 device\n"); goto err_v4l2; } /* encoder */ vfd = video_device_alloc(); if (!vfd) { v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); ret = -ENOMEM; goto err_vd_alloc_enc; } *vfd = jpeg_enc_videodev; vfd->ioctl_ops = get_jpeg_enc_v4l2_ioctl_ops(); ret = video_register_device(vfd, VFL_TYPE_GRABBER, 12); if (ret) { v4l2_err(&dev->v4l2_dev, "%s(): failed to register video device\n", __func__); video_device_release(vfd); goto err_vd_alloc_enc; } v4l2_info(&dev->v4l2_dev, "JPEG driver is registered to /dev/video%d\n", vfd->num); dev->vfd_enc = vfd; dev->m2m_dev_enc = v4l2_m2m_init(&jpeg_m2m_enc_ops); if (IS_ERR(dev->m2m_dev_enc)) { v4l2_err(&dev->v4l2_dev, "failed to initialize v4l2-m2m device\n"); ret = PTR_ERR(dev->m2m_dev_enc); goto err_m2m_init_enc; } video_set_drvdata(vfd, dev); /* decoder */ vfd = video_device_alloc(); if (!vfd) { v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); ret = -ENOMEM; goto err_vd_alloc_dec; } *vfd = jpeg_dec_videodev; vfd->ioctl_ops = get_jpeg_dec_v4l2_ioctl_ops(); ret = video_register_device(vfd, VFL_TYPE_GRABBER, 11); if (ret) { v4l2_err(&dev->v4l2_dev, "%s(): failed to register video device\n", __func__); video_device_release(vfd); goto err_vd_alloc_dec; } v4l2_info(&dev->v4l2_dev, "JPEG driver is registered to /dev/video%d\n", vfd->num); dev->vfd_dec = vfd; dev->m2m_dev_dec = v4l2_m2m_init(&jpeg_m2m_dec_ops); if (IS_ERR(dev->m2m_dev_dec)) { v4l2_err(&dev->v4l2_dev, "failed to initialize v4l2-m2m device\n"); ret = PTR_ERR(dev->m2m_dev_dec); goto err_m2m_init_dec; } video_set_drvdata(vfd, dev); platform_set_drvdata(pdev, dev); #ifdef CONFIG_VIDEOBUF2_CMA_PHYS dev->vb2 = &jpeg_vb2_cma; #elif defined(CONFIG_VIDEOBUF2_ION) dev->vb2 = &jpeg_vb2_ion; #endif dev->alloc_ctx = dev->vb2->init(dev); if (IS_ERR(dev->alloc_ctx)) { ret = PTR_ERR(dev->alloc_ctx); goto err_video_reg; } #ifdef CONFIG_BUSFREQ_OPP /* To lock bus frequency in OPP mode */ dev->bus_dev = dev_get("exynos-busfreq"); #endif dev->watchdog_workqueue = create_singlethread_workqueue(JPEG_NAME); INIT_WORK(&dev->watchdog_work, jpeg_watchdog_worker); atomic_set(&dev->watchdog_cnt, 0); init_timer(&dev->watchdog_timer); dev->watchdog_timer.data = (unsigned long)dev; dev->watchdog_timer.function = jpeg_watchdog; /* clock disable */ clk_disable(dev->clk); return 0; err_video_reg: v4l2_m2m_release(dev->m2m_dev_dec); err_m2m_init_dec: video_unregister_device(dev->vfd_dec); video_device_release(dev->vfd_dec); err_vd_alloc_dec: v4l2_m2m_release(dev->m2m_dev_enc); err_m2m_init_enc: video_unregister_device(dev->vfd_enc); video_device_release(dev->vfd_enc); err_vd_alloc_enc: v4l2_device_unregister(&dev->v4l2_dev); err_v4l2: clk_disable(dev->clk); clk_put(dev->clk); err_clk: free_irq(dev->irq_no, NULL); err_irq: iounmap(dev->reg_base); err_map: err_region: kfree(res); err_res: mutex_destroy(&dev->lock); err_setup: kfree(dev); err_alloc: return ret; }
static long jpeg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; struct jpeg_control *ctrl; ctrl = (struct jpeg_control *)file->private_data; if (!ctrl) { jpeg_err("jpeg invalid input argument\n"); return -1; } switch (cmd) { case IOCTL_JPEG_DEC_EXE: ret = copy_from_user(&ctrl->dec_param, (struct jpeg_dec_param *)arg, sizeof(struct jpeg_dec_param)); jpeg_exe_dec(ctrl); ret = copy_to_user((void *)arg, (void *) &ctrl->dec_param, sizeof(struct jpeg_dec_param)); break; case IOCTL_JPEG_ENC_EXE: ret = copy_from_user(&ctrl->enc_param, (struct jpeg_enc_param *)arg, sizeof(struct jpeg_enc_param)); jpeg_exe_enc(ctrl); ret = copy_to_user((void *)arg, (void *) &ctrl->enc_param, sizeof(struct jpeg_enc_param)); break; case IOCTL_GET_DEC_IN_BUF: case IOCTL_GET_ENC_OUT_BUF: return jpeg_get_stream_buf(arg); case IOCTL_GET_DEC_OUT_BUF: case IOCTL_GET_ENC_IN_BUF: return jpeg_get_frame_buf(arg); case IOCTL_GET_PHYADDR: return jpeg_ctrl->mem.frame_data_addr; case IOCTL_GET_PHYMEM_BASE: #ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_JPEG if (copy_to_user((void *)arg, &jpeg_ctrl->mem.base, sizeof(unsigned int))) { jpeg_err("IOCTL_GET_PHYMEM_BASE:::copy_to_user error\n"); return -1; } return 0; #else return -1; #endif case IOCTL_GET_PHYMEM_SIZE: #ifdef CONFIG_VIDEO_SAMSUNG_MEMSIZE_JPEG ret = CONFIG_VIDEO_SAMSUNG_MEMSIZE_JPEG * 1024; if (copy_to_user((void *)arg, &ret, sizeof(unsigned int))) { jpeg_err("IOCTL_GET_PHYMEM_SIZE:::copy_to_user error\n"); return -1; } return 0; #else return -1; #endif case IOCTL_SET_DEC_PARAM: ret = copy_from_user(&ctrl->dec_param, (struct jpeg_dec_param *)arg, sizeof(struct jpeg_dec_param)); ret = jpeg_set_dec_param(ctrl); break; case IOCTL_SET_ENC_PARAM: ret = copy_from_user(&ctrl->enc_param, (struct jpeg_enc_param *)arg, sizeof(struct jpeg_enc_param)); ret = jpeg_set_enc_param(ctrl); break; default: break; } return 0; }
static long jpeg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; struct jpeg_control *ctrl; ctrl = (struct jpeg_control *)file->private_data; if (!ctrl) { jpeg_err("jpeg invalid input argument\n"); return -1; } switch (cmd) { case IOCTL_JPEG_DEC_EXE: ret = copy_from_user(&ctrl->dec_param, (struct jpeg_dec_param *)arg, sizeof(struct jpeg_dec_param)); jpeg_exe_dec(ctrl); ret = copy_to_user((void *)arg, (void *) &ctrl->dec_param, sizeof(struct jpeg_dec_param)); break; case IOCTL_JPEG_ENC_EXE: ret = copy_from_user(&ctrl->enc_param, (struct jpeg_enc_param *)arg, sizeof(struct jpeg_enc_param)); jpeg_exe_enc(ctrl); ret = copy_to_user((void *)arg, (void *) &ctrl->enc_param, sizeof(struct jpeg_enc_param)); break; case IOCTL_GET_DEC_IN_BUF: case IOCTL_GET_ENC_OUT_BUF: return jpeg_get_stream_buf(arg); case IOCTL_GET_DEC_OUT_BUF: case IOCTL_GET_ENC_IN_BUF: return jpeg_get_frame_buf(arg); case IOCTL_SET_DEC_PARAM: ret = copy_from_user(&ctrl->dec_param, (struct jpeg_dec_param *)arg, sizeof(struct jpeg_dec_param)); ret = jpeg_set_dec_param(ctrl); break; case IOCTL_SET_ENC_PARAM: ret = copy_from_user(&ctrl->enc_param, (struct jpeg_enc_param *)arg, sizeof(struct jpeg_enc_param)); ret = jpeg_set_enc_param(ctrl); break; default: break; } return 0; }
static int jpeg_probe(struct platform_device *pdev) { struct resource *res; int ret; /* global structure */ jpeg_ctrl = kzalloc(sizeof(*jpeg_ctrl), GFP_KERNEL); if (!jpeg_ctrl) { dev_err(&pdev->dev, "%s: not enough memory\n", __func__); ret = -ENOMEM; goto err_alloc; } /* setup jpeg control */ ret = jpeg_setup_controller(jpeg_ctrl); if (ret) { jpeg_err("failed to setup controller\n"); goto err_setup; } /* memory region */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { jpeg_err("failed to get jpeg memory region resource\n"); ret = -ENOENT; goto err_res; } res = request_mem_region(res->start, res->end - res->start + 1, pdev->name); if (!res) { jpeg_err("failed to request jpeg io memory region\n"); ret = -ENOMEM; goto err_region; } /* ioremap */ jpeg_ctrl->reg_base = ioremap(res->start, res->end - res->start + 1); if (!jpeg_ctrl->reg_base) { jpeg_err("failed to remap jpeg io region\n"); ret = -ENOENT; goto err_map; } /* irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { jpeg_err("failed to request jpeg irq resource\n"); ret = -ENOENT; goto err_irq; } jpeg_ctrl->irq_no = res->start; ret = request_irq(jpeg_ctrl->irq_no, (void *)jpeg_irq, IRQF_DISABLED, pdev->name, jpeg_ctrl); if (ret != 0) { jpeg_err("failed to jpeg request irq\n"); ret = -ENOENT; goto err_irq; } /* clock */ jpeg_ctrl->clk = clk_get(&pdev->dev, "jpeg"); if (IS_ERR(jpeg_ctrl->clk)) { jpeg_err("failed to find jpeg clock source\n"); ret = -ENOENT; goto err_clk; } ret = jpeg_init_mem(&pdev->dev, &jpeg_ctrl->mem.base); if (ret != 0) { jpeg_err("failed to init. jpeg mem"); ret = -ENOMEM; goto err_mem; } ret = misc_register(&jpeg_miscdev); if (ret) { jpeg_err("failed to register misc driver\n"); goto err_reg; } jpeg_pm = &pdev->dev; #ifdef CONFIG_PM_RUNTIME pm_runtime_enable(jpeg_pm); #endif return 0; err_reg: clk_put(jpeg_ctrl->clk); err_mem: err_clk: free_irq(jpeg_ctrl->irq_no, NULL); err_irq: iounmap(jpeg_ctrl->reg_base); err_map: err_region: kfree(res); err_res: mutex_destroy(&jpeg_ctrl->lock); err_setup: kfree(jpeg_ctrl); err_alloc: return ret; }