diff options
Diffstat (limited to 'drivers/media/video/samsung/mfc5x/mfc_dev.c')
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_dev.c | 119 |
1 files changed, 118 insertions, 1 deletions
diff --git a/drivers/media/video/samsung/mfc5x/mfc_dev.c b/drivers/media/video/samsung/mfc5x/mfc_dev.c index e3a0b60..23bc10d 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_dev.c +++ b/drivers/media/video/samsung/mfc5x/mfc_dev.c @@ -66,6 +66,10 @@ #include <plat/sysmmu.h> #endif +#ifdef CONFIG_SLP_DMABUF +#include <media/videobuf2-core.h> +#endif + #define MFC_MINOR 252 #define MFC_FW_NAME "mfc_fw.bin" @@ -108,6 +112,79 @@ static inline void clear_magic(unsigned char *addr) } #endif +#ifdef CONFIG_SLP_DMABUF +/** + * _mfc_dmabuf_put() - release memory associated with + * a DMABUF shared buffer + */ +static void _mfc_dmabuf_put(struct vb2_plane *planes) +{ + unsigned int plane; + + for (plane = 0; plane < MFC_NUM_PLANE; ++plane) { + void *mem_priv = planes[plane].mem_priv; + + if (mem_priv) { + dma_buf_detach(planes[plane].dbuf, + planes[plane].mem_priv); + dma_buf_put(planes[plane].dbuf); + planes[plane].dbuf = NULL; + planes[plane].mem_priv = NULL; + } + } +} + +void mfc_queue_free(struct mfc_inst_ctx *mfc_ctx) +{ + struct vb2_plane *planes; + int buffer; + + for (buffer = 0; buffer < VIDEO_MAX_PLANES; ++buffer) { + planes = mfc_ctx->enc_planes[buffer]; + + if (!planes) + continue; + + _mfc_dmabuf_put(planes); + kfree(planes); + planes = NULL; + } +} + +int mfc_queue_alloc(struct mfc_inst_ctx *mfc_ctx) +{ + struct vb2_plane *planes; + int buffer; + int ret = 0; + + for (buffer = 0; buffer < MFC_NUM_PLANE; ++buffer) { + planes = kzalloc(sizeof(struct vb2_plane), GFP_KERNEL); + if (!planes) { + printk(KERN_INFO "MFC Queue memory alloc failed\n"); + ret = -ENOMEM; + goto err; + } + + planes->mem_priv = NULL; + mfc_ctx->enc_planes[buffer] = planes; + } + + for (buffer = MFC_NUM_PLANE; buffer < VIDEO_MAX_PLANES; ++buffer) + mfc_ctx->enc_planes[buffer] = NULL; + + return ret; + +err: + for (buffer = 0; buffer < VIDEO_MAX_PLANES; buffer++) { + if (mfc_ctx->enc_planes[buffer] != NULL) + kfree(mfc_ctx->enc_planes[buffer]); + mfc_ctx->enc_planes[buffer] = NULL; + } + + return ret; +} +#endif + static int get_free_inst_id(struct mfc_dev *dev) { int slot = 0; @@ -135,6 +212,25 @@ static int mfc_open(struct inode *inode, struct file *file) file->private_data = NULL; mutex_lock(&mfcdev->lock); + +#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0) + if (atomic_read(&mfcdev->inst_cnt) == 0) { + size_t size = 0x02800000; + mfcdev->cma_vaddr = dma_alloc_coherent(mfcdev->device, size, + &mfcdev->cma_dma_addr, 0); + if (!mfcdev->cma_vaddr) { + printk(KERN_ERR "%s: dma_alloc_coherent returns " + "-ENOMEM\n", __func__); + mutex_unlock(&mfcdev->lock); + return -ENOMEM; + } + printk(KERN_INFO "%s[%d] size 0x%x, vaddr 0x%x, base 0x%x\n", + __func__, __LINE__, (int)size, + (int)mfcdev->cma_vaddr, + (int)mfcdev->cma_dma_addr); + } +#endif + #if SUPPORT_SLICE_ENCODING mfcdev->frame_working_flag = 1; mfcdev->frame_sys = 0; @@ -292,6 +388,13 @@ static int mfc_open(struct inode *inode, struct file *file) if (mfcdev->wait_frame_timeout == 1) wake_up(&mfcdev->wait_frame); #endif +#ifdef CONFIG_SLP_DMABUF + ret = mfc_queue_alloc(mfc_ctx); + if (ret < 0) { + mfc_err("mfc_queue_alloc failed\n"); + goto err_inst_ctx; + } +#endif mfc_info("MFC instance [%d:%d] opened", mfc_ctx->id, atomic_read(&mfcdev->inst_cnt)); @@ -456,10 +559,24 @@ static int mfc_release(struct inode *inode, struct file *file) if (mfcdev->wait_frame_timeout == 1) wake_up(&dev->wait_frame); #endif +#ifdef CONFIG_SLP_DMABUF + mfc_queue_free(mfc_ctx); +#endif err_pwr_disable: - mutex_unlock(&dev->lock); +#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0) + if (atomic_read(&mfcdev->inst_cnt) == 0) { + size_t size = 0x02800000; + dma_free_coherent(mfcdev->device, size, mfcdev->cma_vaddr, + mfcdev->cma_dma_addr); + printk(KERN_INFO "%s[%d] size 0x%x, vaddr 0x%x, base 0x0%x\n", + __func__, __LINE__, (int)size, + (int) mfcdev->cma_vaddr, + (int)mfcdev->cma_dma_addr); + } +#endif + mutex_unlock(&dev->lock); return ret; } |