diff options
author | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 09:48:20 +0200 |
---|---|---|
committer | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 14:02:16 +0200 |
commit | 2489007e7d740ccbc3e0a202914e243ad5178787 (patch) | |
tree | b8e6380ea7b1da63474ad68a5dba997e01146043 /drivers/media/video/samsung/mfc5x | |
parent | 5f67568eb31e3a813c7c52461dcf66ade15fc2e7 (diff) | |
download | kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.zip kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.gz kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.bz2 |
merge opensource jb u5
Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2
Diffstat (limited to 'drivers/media/video/samsung/mfc5x')
-rw-r--r-- | drivers/media/video/samsung/mfc5x/Kconfig | 12 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h | 19 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc.h | 4 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_buf.c | 287 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_buf.h | 10 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_dec.c | 90 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_dec.h | 5 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_dev.c | 119 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_dev.h | 6 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_enc.c | 205 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_enc.h | 1 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_inst.c | 1 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_inst.h | 9 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_interface.h | 6 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_mem.c | 39 | ||||
-rw-r--r-- | drivers/media/video/samsung/mfc5x/mfc_shm.h | 2 |
16 files changed, 783 insertions, 32 deletions
diff --git a/drivers/media/video/samsung/mfc5x/Kconfig b/drivers/media/video/samsung/mfc5x/Kconfig index 0ff8a60..57858ed 100644 --- a/drivers/media/video/samsung/mfc5x/Kconfig +++ b/drivers/media/video/samsung/mfc5x/Kconfig @@ -9,8 +9,8 @@ config VIDEO_MFC5X This is a Samsung Multi Format Codecs (MFC) FIMV V5.x config VIDEO_MFC_MAX_INSTANCE - int "Maximum size of MFC instance (1-4)" - range 1 4 + int "Maximum size of MFC instance (1-8)" + range 1 8 depends on VIDEO_MFC5X default 4 @@ -36,4 +36,10 @@ config VIDEO_MFC5X_DEC_CHROMA_LUMA_4K_ALIGN ---help--- To use physical address on the gem interface. - +config USE_MFC_CMA + bool "Use CMA for MFC_SECURE region (EXPERIMENTAL)" + depends on DMA_CMA + default n + help + This enables the Contiguous Memory Allocator for MFC SECURE region. + If unsure, say "n". diff --git a/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h b/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h index ba4b736..cbf6cab 100644 --- a/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h +++ b/drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h @@ -41,11 +41,20 @@ #define SAMSUNG_MFC_DEV_NAME "/dev/s3c-mfc" #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) -#define SUPPORT_SLICE_ENCODING 0 // This is originally 1, but breaks video recording on AOSP :( +#define SUPPORT_SLICE_ENCODING 0 // originaly 1, but we're missing matching userspace #else #define SUPPORT_SLICE_ENCODING 0 #endif +/*---------------------------*/ +/* Memory Type */ +/*---------------------------*/ +typedef enum { + MEMORY_PHY_ADDR = 0, + MEMORY_USRPTR = 1, + MEMORY_DMABUF = 2, +} SSBSIP_MFC_MEMORY_TYPE; + /*--------------------------------------------------------------------------------*/ /* Structure and Type */ /*--------------------------------------------------------------------------------*/ @@ -127,6 +136,7 @@ typedef enum { /* C210 specific feature */ MFC_ENC_SETCONF_VUI_INFO, MFC_ENC_SETCONF_I_PERIOD, + MFC_ENC_SETCONF_SPS_PPS_GEN, MFC_ENC_SETCONF_HIER_P, MFC_ENC_SETCONF_SEI_GEN, @@ -139,7 +149,12 @@ typedef enum { MFC_GETOUTBUF_DISPLAY_DECODING, MFC_GETOUTBUF_DISPLAY_ONLY, MFC_GETOUTBUF_DISPLAY_END, - MFC_GETOUTBUF_CHANGE_RESOL +#ifndef CONFIG_SLP + MFC_GETOUTBUF_CHANGE_RESOL +#else + MFC_GETOUTBUF_CHANGING_RESOL, + MFC_GETOUTBUF_CHANGE_RESOL_DONE +#endif } SSBSIP_MFC_DEC_OUTBUF_STATUS; typedef enum { diff --git a/drivers/media/video/samsung/mfc5x/mfc.h b/drivers/media/video/samsung/mfc5x/mfc.h index de1849c..a8c5d72 100644 --- a/drivers/media/video/samsung/mfc5x/mfc.h +++ b/drivers/media/video/samsung/mfc5x/mfc.h @@ -98,4 +98,8 @@ #endif #endif +#ifdef CONFIG_SLP +#define MFC_NUM_PLANE 2 +#endif + #endif /* __MFC_H_ */ diff --git a/drivers/media/video/samsung/mfc5x/mfc_buf.c b/drivers/media/video/samsung/mfc5x/mfc_buf.c index e0e243d..d841a37 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_buf.c +++ b/drivers/media/video/samsung/mfc5x/mfc_buf.c @@ -16,6 +16,13 @@ #include <linux/mm.h> #include <linux/err.h> +#ifdef CONFIG_SLP +#include <linux/cma.h> +#ifdef CONFIG_SLP_DMABUF +#include <linux/dma-buf.h> +#endif +#endif + #include "mfc.h" #include "mfc_mem.h" #include "mfc_buf.h" @@ -30,6 +37,168 @@ #include "ump_kernel_interface_vcm.h" #endif +#ifdef CONFIG_SLP_DMABUF +struct mfc_dmabuf_buf { + dma_addr_t dma_addr; + unsigned long size; + /* fd exported from this buf object. */ + int export_fd; + /* dma buf exported from this buf object. */ + struct dma_buf *export_dma_buf; + struct dma_buf_attachment *db_attach; + atomic_t refcount; +}; + +static void _mfc_dmabuf_put(struct mfc_dmabuf_buf *buf) +{ + if (atomic_dec_and_test(&buf->refcount)) { + /* + * In legacy driver, dmabuf functions don't control + * cma memory allocation and free. + * so, currently we comment cma_free function. + * cma_free(buf->dma_addr); + */ + kfree(buf); + } +} + +static int mfc_attach_dmabuf(struct dma_buf *dmabuf, struct device *dev, + struct dma_buf_attachment *attach) +{ + mfc_dbg("mfc_attach_dmabuf: called !\n"); + return 0; +} + +static void mfc_detach_dmabuf(struct dma_buf *dmabuf, + struct dma_buf_attachment *attach) +{ + mfc_dbg("mfc_detach_dmabuf: called !\n"); + dma_buf_put(dmabuf); +} + +static struct sg_table * + mfc_map_dmabuf(struct dma_buf_attachment *attach, + enum dma_data_direction direction) +{ + struct mfc_dmabuf_buf *buf; + struct sg_table *sgt; + int ret; + int val; + + mfc_dbg("mfc_map_dmabuf: called !\n"); + if (!attach->dmabuf->priv) { + mfc_err("mfc_map_dmabuf: failed : attach->dmabuf->priv is NULL\n"); + return NULL; + } + buf = attach->dmabuf->priv; + sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sgt) { + mfc_err("mfc_map_dmabuf: failed to allocate sg table.\n"); + return ERR_PTR(-ENOMEM); + } + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (ret < 0) { + mfc_err("mfc_map_dmabuf: failed to allocate scatter list.\n"); + kfree(sgt); + sgt = NULL; + return ERR_PTR(-ENOMEM); + } + + sg_init_table(sgt->sgl, 1); + sg_dma_len(sgt->sgl) = buf->size; + sg_set_page(sgt->sgl, pfn_to_page(PFN_DOWN(buf->dma_addr)), + buf->size, 0); + sg_dma_address(sgt->sgl) = buf->dma_addr; + + /* + * increase reference count of this buf object. + * + * Note: + * alloated physical memory region is being shared with others so + * this region shouldn't be released until all references of this + * region will be dropped by mfc_unmap_dmabuf(). + */ + val = atomic_inc_return(&buf->refcount); + mfc_dbg("mfc_map_dmabuf: refcount: %d\n", val); + + return sgt; +} + +static void mfc_unmap_dmabuf(struct dma_buf_attachment *attach, + struct sg_table *sgt, enum dma_data_direction direction) +{ + int val = 0; + struct mfc_dmabuf_buf *buf; + + mfc_dbg("mfc_unmap_dmabuf: called !\n"); + buf = attach->dmabuf->priv; + + sg_free_table(sgt); + kfree(sgt); + sgt = NULL; + + val = atomic_dec_return(&buf->refcount); + mfc_dbg("mfc_unmap_dmabuf: refcount: %d\n", val); +} + +static void mfc_release_dmabuf(struct dma_buf *dmabuf) +{ + struct mfc_dmabuf_buf *buf; + + mfc_dbg("mfc_release_dmabuf: called !\n"); + if (!dmabuf->priv) { + mfc_dbg("mfc_release_dmabuf: failed: dmabuf->priv is NULL\n"); + return; + } + buf = dmabuf->priv; + if (buf->export_dma_buf == dmabuf) { + mfc_dbg("mfc_release_dmabuf: called !\n"); + buf->export_fd = -1; + buf->export_dma_buf = NULL; + + _mfc_dmabuf_put(buf); + } +} + +static void *mfc_kmap_atomic_dmabuf(struct dma_buf *dma_buf, + unsigned long page_num) +{ + return NULL; +} + +static void mfc_kunmap_atomic_dmabuf(struct dma_buf *dma_buf, + unsigned long page_num, + void *addr) +{ + +} + +static void *mfc_kmap_dmabuf(struct dma_buf *dma_buf, + unsigned long page_num) +{ + return NULL; +} + +static void mfc_kunmap_dmabuf(struct dma_buf *dma_buf, + unsigned long page_num, void *addr) +{ + +} + +static struct dma_buf_ops mfc_dmabuf_ops = { + .attach = mfc_attach_dmabuf, + .detach = mfc_detach_dmabuf, + .map_dma_buf = mfc_map_dmabuf, + .unmap_dma_buf = mfc_unmap_dmabuf, + .release = mfc_release_dmabuf, + .kmap = mfc_kmap_dmabuf, + .kmap_atomic = mfc_kmap_atomic_dmabuf, + .kunmap = mfc_kunmap_dmabuf, + .kunmap_atomic = mfc_kunmap_atomic_dmabuf, +}; +#endif + #define PRINT_BUF #undef DEBUG_ALLOC_FREE @@ -122,7 +291,7 @@ static int mfc_put_free_buf(unsigned long addr, unsigned int size, int port) /* 0x00: not merged, 0x01: prev merged, 0x02: next merged */ int merged = 0x00; - if (!size) + if ((!size) || (port >= MFC_MAX_MEM_PORT_NUM)) return -EINVAL; mfc_dbg("addr: 0x%08lx, size: %d, port: %d\n", addr, size, port); @@ -376,6 +545,13 @@ void mfc_final_buf(void) kfree(alloc); } #else +#ifdef CONFIG_SLP + if (alloc->real) { + cma_free(alloc->real); + list_del(&alloc->list); + kfree(alloc); + } +#else if (mfc_put_free_buf(alloc->real, alloc->size, port) < 0) { @@ -385,6 +561,7 @@ void mfc_final_buf(void) kfree(alloc); } #endif +#endif } } @@ -466,6 +643,15 @@ struct mfc_alloc_buffer *_mfc_alloc_buf( #elif defined(CONFIG_S5P_VMEM) int align_size = 0; #endif +#ifdef CONFIG_SLP + struct mfc_dev *dev = ctx->dev; + size_t available_size; + struct cma_info cma_infos; +#ifdef CONFIG_SLP_DMABUF + struct mfc_dmabuf_buf *buf; + int flags = 0; +#endif +#endif /* unsigned long flags; */ @@ -486,8 +672,62 @@ struct mfc_alloc_buffer *_mfc_alloc_buf( /* spin_lock_irqsave(&lock, flags); */ +#ifdef CONFIG_SLP + if (cma_info(&cma_infos, dev->device, port ? "B" : "A")) { + mfc_info("failed to get CMA info of 'mfc'\n"); + kfree(alloc); + return NULL; + } + available_size = cma_infos.free_size; + if (available_size > MAX_MEM_OFFSET) { + mfc_warn("<Warning> too large 'mfc' reserved memory, " + "size will be shrink (%d:%d)\n", + size >> 10, MAX_MEM_OFFSET >> 10); + size = MAX_MEM_OFFSET; + } + addr = cma_alloc(dev->device, port ? "B" : "A", size, align); + if (IS_ERR_VALUE(addr)) { + mfc_err("failed to get rsv. memory from CMA"); + kfree(alloc); + return NULL; + } +#ifdef CONFIG_SLP_DMABUF + buf = kzalloc(sizeof(struct mfc_dmabuf_buf), GFP_KERNEL); + if (!buf) { + mfc_err("failed to alloc mfc_dmabuf_buf"); + kfree(alloc); + cma_free(addr); + return NULL; + } + buf->dma_addr = addr; + buf->size = size; + + buf->export_dma_buf = dma_buf_export(buf, &mfc_dmabuf_ops, + buf->size, 0600); + if (!buf->export_dma_buf) { + mfc_err("fail to export dma_buf\n"); + kfree(alloc); + cma_free(addr); + kfree(buf); + return NULL; + } + buf->export_fd = dma_buf_fd(buf->export_dma_buf, flags); + if (buf->export_fd < 0) { + mfc_err(" fail to get fd from dmabuf.\n"); + kfree(alloc); + cma_free(addr); + kfree(buf); + dma_buf_put(buf->export_dma_buf); + return NULL; + } + alloc->dmabuf_fd = buf->export_fd; + atomic_inc(&buf->refcount); + mfc_dbg(" buf->export_fd = %d\n", buf->export_fd); +#endif +#else addr = mfc_get_free_buf(size, align, port); +#endif mfc_dbg("mfc_get_free_buf: 0x%08lx\n", addr); @@ -783,15 +1023,22 @@ int _mfc_free_buf(unsigned long real) kfree(alloc); } #else +#ifdef CONFIG_SLP + if (alloc->real) { + cma_free(alloc->real); + list_del(&alloc->list); + kfree(alloc); + } +#else if (mfc_put_free_buf(alloc->real, alloc->size, port) < 0) { - mfc_err("failed to add free buffer\n"); } else { list_del(&alloc->list); kfree(alloc); } #endif +#endif break; } } @@ -839,6 +1086,13 @@ void mfc_free_buf_type(int owner, int type) alloc = list_entry(pos, struct mfc_alloc_buffer, list); if ((alloc->owner == owner) && (alloc->type == type)) { +#ifdef CONFIG_SLP + if (alloc->real) { + cma_free(alloc->real); + list_del(&alloc->list); + kfree(alloc); + } +#else if (mfc_put_free_buf(alloc->real, alloc->size, port) < 0) { @@ -847,6 +1101,7 @@ void mfc_free_buf_type(int owner, int type) list_del(&alloc->list); kfree(alloc); } +#endif } } } @@ -905,6 +1160,13 @@ void mfc_free_buf_inst(int owner) kfree(alloc); } #else +#ifdef CONFIG_SLP + if (alloc->real) { + cma_free(alloc->real); + list_del(&alloc->list); + kfree(alloc); + } +#else if (mfc_put_free_buf(alloc->real, alloc->size, port) < 0) { @@ -914,6 +1176,7 @@ void mfc_free_buf_inst(int owner) kfree(alloc); } #endif +#endif } } } @@ -1034,4 +1297,24 @@ void *mfc_get_buf_ump_handle(unsigned long real) return NULL; } #endif +#ifdef CONFIG_SLP_DMABUF +int mfc_get_buf_dmabuf(unsigned long real) +{ + struct list_head *pos, *nxt; + int port; + struct mfc_alloc_buffer *alloc; + + mfc_dbg("real: 0x%08lx\n", real); + for (port = 0; port < mfc_mem_count(); port++) { + list_for_each_safe(pos, nxt, &mfc_alloc_head[port]) { + alloc = list_entry(pos, struct mfc_alloc_buffer, list); + + if (alloc->real == real) + return alloc->dmabuf_fd; + } + } + + return -EINVAL; +} +#endif diff --git a/drivers/media/video/samsung/mfc5x/mfc_buf.h b/drivers/media/video/samsung/mfc5x/mfc_buf.h index 7fafb94..28ef0d6 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_buf.h +++ b/drivers/media/video/samsung/mfc5x/mfc_buf.h @@ -142,6 +142,10 @@ struct mfc_alloc_buffer { unsigned char *addr; /* kernel virtual address space */ unsigned int type; /* buffer type */ int owner; /* instance context id */ +#if defined(CONFIG_DMA_CMA) && defined(CONFIG_USE_MFC_CMA) + struct device *dev; + dma_addr_t dma_addr; +#endif #if defined(CONFIG_VIDEO_MFC_VCM_UMP) struct vcm_mmu_res *vcm_s; struct vcm_res *vcm_k; @@ -159,6 +163,9 @@ struct mfc_alloc_buffer { * when user use mmap, * user can access whole of memory by offset. */ +#ifdef CONFIG_SLP_DMABUF + int dmabuf_fd; +#endif #endif }; @@ -187,6 +194,9 @@ unsigned long mfc_get_buf_real(int owner, unsigned int key); unsigned char *mfc_get_buf_addr(int owner, unsigned char *user); unsigned char *_mfc_get_buf_addr(int owner, unsigned char *user); */ +#ifdef CONFIG_SLP_DMABUF +int mfc_get_buf_dmabuf(unsigned long real); +#endif #ifdef CONFIG_VIDEO_MFC_VCM_UMP unsigned int mfc_vcm_bind_from_others(struct mfc_inst_ctx *ctx, struct mfc_buf_alloc_arg *args, int flag); diff --git a/drivers/media/video/samsung/mfc5x/mfc_dec.c b/drivers/media/video/samsung/mfc5x/mfc_dec.c index fd78b7d..d3d336a 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_dec.c +++ b/drivers/media/video/samsung/mfc5x/mfc_dec.c @@ -1882,15 +1882,6 @@ int mfc_init_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args) dec_ctx->numtotaldpb); #if defined(CONFIG_BUSFREQ) -#if defined(CONFIG_CPU_EXYNOS4210) - /* Fix MFC & Bus Frequency for better performance */ - if (atomic_read(&ctx->dev->busfreq_lock_cnt) == 0) { - exynos4_busfreq_lock(DVFS_LOCK_ID_MFC, BUS_L1); - mfc_dbg("Bus FREQ locked to L1\n"); - } - atomic_inc(&ctx->dev->busfreq_lock_cnt); - ctx->busfreq_flag = true; -#else /* Lock MFC & Bus FREQ for high resolution */ if (ctx->width >= MAX_HOR_RES || ctx->height >= MAX_VER_RES) { if (atomic_read(&ctx->dev->busfreq_lock_cnt) == 0) { @@ -1900,8 +1891,17 @@ int mfc_init_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args) atomic_inc(&ctx->dev->busfreq_lock_cnt); ctx->busfreq_flag = true; - } + } else { +#if defined(CONFIG_CPU_EXYNOS4210) + /* Fix MFC & Bus Frequency for better performance */ + if (atomic_read(&ctx->dev->busfreq_lock_cnt) == 0) { + exynos4_busfreq_lock(DVFS_LOCK_ID_MFC, BUS_L1); + mfc_dbg("Bus FREQ locked to L1\n"); + } + atomic_inc(&ctx->dev->busfreq_lock_cnt); + ctx->busfreq_flag = true; #endif + } #endif #if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_EXYNOS4_CPUFREQ) @@ -1926,8 +1926,12 @@ int mfc_init_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args) dmc_max_threshold = EXYNOS4212_DMC_MAX_THRESHOLD + 5; } else if (soc_is_exynos4412()) { - dmc_max_threshold = - EXYNOS4412_DMC_MAX_THRESHOLD + 5; + if (samsung_rev() >= EXYNOS4412_REV_2_0) + dmc_max_threshold = + PRIME_DMC_MAX_THRESHOLD + 5; + else + dmc_max_threshold = + EXYNOS4412_DMC_MAX_THRESHOLD + 5; } else { pr_err("Unsupported model.\n"); return -EINVAL; @@ -2093,6 +2097,25 @@ int mfc_change_resolution(struct mfc_inst_ctx *ctx, struct mfc_dec_exe_arg *exe_ } ret = mfc_cmd_init_buffers(ctx); + +#ifdef CONFIG_SLP + if (ctx->codecid == H264_DEC) { + exe_arg->out_crop_right_offset = + (read_shm(ctx, CROP_INFO1) >> 16) & 0xFFFF; + exe_arg->out_crop_left_offset = + read_shm(ctx, CROP_INFO1) & 0xFFFF; + exe_arg->out_crop_bottom_offset = + (read_shm(ctx, CROP_INFO2) >> 16) & 0xFFFF; + exe_arg->out_crop_top_offset = + read_shm(ctx, CROP_INFO2) & 0xFFFF; + + mfc_dbg("mfc_change_resolution: crop info t: %d, r: %d, b: %d, l: %d\n", + exe_arg->out_crop_top_offset, + exe_arg->out_crop_right_offset, + exe_arg->out_crop_bottom_offset, + exe_arg->out_crop_left_offset); + } +#endif if (ret < 0) return ret; @@ -2126,7 +2149,7 @@ static int mfc_decoding_frame(struct mfc_inst_ctx *ctx, struct mfc_dec_exe_arg * unsigned char *stream_vir; int ret; struct mfc_dec_ctx *dec_ctx = (struct mfc_dec_ctx *)ctx->c_priv; - unsigned long mem_ofs; + long mem_ofs; #ifdef CONFIG_VIDEO_MFC_VCM_UMP void *ump_handle; #endif @@ -2265,9 +2288,29 @@ static int mfc_decoding_frame(struct mfc_inst_ctx *ctx, struct mfc_dec_exe_arg * exe_arg->out_display_status = dec_ctx->dispstatus; - exe_arg->out_display_Y_addr = (display_luma_addr << 11); - exe_arg->out_display_C_addr = (display_chroma_addr << 11); - +#ifdef CONFIG_SLP_DMABUF + if (exe_arg->memory_type == MEMORY_DMABUF) { + exe_arg->out_display_Y_addr = + mfc_get_buf_dmabuf(display_luma_addr << 11); + if (exe_arg->out_display_Y_addr < 0) { + mfc_err("mfc_get_buf_dmabuf : Get Y fd error %d\n", + exe_arg->out_display_Y_addr); + return MFC_DEC_EXE_ERR; + } + exe_arg->out_display_C_addr = + mfc_get_buf_dmabuf(display_chroma_addr << 11); + if (exe_arg->out_display_C_addr < 0) { + mfc_err("mfc_get_buf_dmabuf : Get C fd error %d\n", + exe_arg->out_display_C_addr); + return MFC_DEC_EXE_ERR; + } + } else { +#endif + exe_arg->out_display_Y_addr = (display_luma_addr << 11); + exe_arg->out_display_C_addr = (display_chroma_addr << 11); +#ifdef CONFIG_SLP_DMABUF + } +#endif exe_arg->out_disp_pic_frame_type = display_frame_type; exe_arg->out_y_offset = mfc_mem_data_ofs(display_luma_addr << 11, 1); @@ -2361,6 +2404,7 @@ int mfc_exec_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args) mfc_check_resolution_change(ctx, exe_arg); if (ctx->resolution_status == RES_SET_CHANGE) { ret = mfc_decoding_frame(ctx, exe_arg, &consumed); +#ifndef CONFIG_SLP } else if ((ctx->resolution_status == RES_WAIT_FRAME_DONE) && (exe_arg->out_display_status == DISP_S_FINISH)) { exe_arg->out_display_status = DISP_S_RES_CHANGE; @@ -2368,6 +2412,20 @@ int mfc_exec_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args) if (ret != MFC_OK) return ret; ctx->resolution_status = RES_NO_CHANGE; +#else + } else if (ctx->resolution_status == RES_WAIT_FRAME_DONE) { + if (exe_arg->out_display_status == DISP_S_FINISH) { + exe_arg->out_display_status = + DISP_S_RES_CHANGE_DONE; + + ret = mfc_change_resolution(ctx, exe_arg); + if (ret != MFC_OK) + return ret; + ctx->resolution_status = RES_NO_CHANGE; + } else + exe_arg->out_display_status = + DISP_S_RES_CHANGING; +#endif } if ((dec_ctx->ispackedpb) && diff --git a/drivers/media/video/samsung/mfc5x/mfc_dec.h b/drivers/media/video/samsung/mfc5x/mfc_dec.h index f59795b..86b7a97 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_dec.h +++ b/drivers/media/video/samsung/mfc5x/mfc_dec.h @@ -44,7 +44,12 @@ enum disp_status { DISP_S_DD = 1, DISP_S_DISPLAY = 2, DISP_S_FINISH = 3, +#ifndef CONFIG_SLP DISP_S_RES_CHANGE = 4, /* not H/W bit */ +#else + DISP_S_RES_CHANGING = 4, /* not H/W bit */ + DISP_S_RES_CHANGE_DONE = 5, /* not H/W bit */ +#endif }; /* decoding status */ 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; } diff --git a/drivers/media/video/samsung/mfc5x/mfc_dev.h b/drivers/media/video/samsung/mfc5x/mfc_dev.h index c82c26c..bb2095c 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_dev.h +++ b/drivers/media/video/samsung/mfc5x/mfc_dev.h @@ -99,6 +99,12 @@ struct mfc_dev { struct mfc_fw fw; +#if defined(CONFIG_DMA_CMA) && defined(CONFIG_USE_MFC_CMA) + /* NEW CMA */ + void *cma_vaddr; + dma_addr_t cma_dma_addr; +#endif + struct s5p_vcm_mmu *_vcm_mmu; struct device *device; diff --git a/drivers/media/video/samsung/mfc5x/mfc_enc.c b/drivers/media/video/samsung/mfc5x/mfc_enc.c index 53f24c9..65d7b6b 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_enc.c +++ b/drivers/media/video/samsung/mfc5x/mfc_enc.c @@ -31,6 +31,11 @@ #include "mfc_buf.h" #include "mfc_interface.h" +#ifdef CONFIG_SLP_DMABUF +#include <linux/dma-buf.h> +#include <media/videobuf2-core.h> +#endif + static LIST_HEAD(mfc_encoders); /* @@ -507,7 +512,7 @@ static int pre_seq_start(struct mfc_inst_ctx *ctx) write_reg(mfc_mem_base_ofs(enc_ctx->streamaddr) >> 11, MFC_ENC_SI_CH1_SB_ADR); write_reg(enc_ctx->streamsize, MFC_ENC_SI_CH1_SB_SIZE); #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) - write_shm(ctx, 1, HW_VERSRION); + write_shm(ctx, 1, HW_VERSION); #endif return 0; @@ -579,6 +584,13 @@ static int h264_pre_seq_start(struct mfc_inst_ctx *ctx) h264->change &= ~(CHG_FRAME_PACKING); } + if (h264->sps_pps_gen == 1) { + write_shm(ctx, + ((h264->sps_pps_gen << 8) | + read_shm(ctx, EXT_ENC_CONTROL)), + EXT_ENC_CONTROL); + } + return 0; } @@ -1050,6 +1062,23 @@ static int h264_set_codec_cfg(struct mfc_inst_ctx *ctx, int type, void *arg) h264->change |= CHG_FRAME_PACKING; break; + + case MFC_ENC_SETCONF_SPS_PPS_GEN: + mfc_dbg("MFC_ENC_SETCONF_SPS_PPS_GEN : %d\n", ctx->state); + + if ((ctx->state < INST_STATE_CREATE) || + (ctx->state > INST_STATE_EXE)) { + mfc_err("MFC_ENC_SETCONF_SPS_PPS_GEN : " + " state is invalid\n"); + return MFC_STATE_INVALID; + } + + if (usercfg->basic.values[0] > 0) + h264->sps_pps_gen = 1; + else + h264->sps_pps_gen = 0; + + break; default: mfc_dbg("invalid set cfg type: 0x%08x\n", type); ret = -2; @@ -1590,6 +1619,65 @@ err_handling: return ret; } +#ifdef CONFIG_SLP_DMABUF +static int mfc_qbuf_dmabuf(struct mfc_inst_ctx *ctx, struct vb2_plane *planes, + int fd, dma_addr_t *dma_addr) +{ + struct sg_table *sg; + struct dma_buf *dbuf; + struct dma_buf_attachment *dba; + + dbuf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dbuf)) { + mfc_err("dmabuf get error!!!\n"); + dma_buf_put(dbuf); + return -EINVAL; + } + + /* Skip the plane if already verified */ + if (dbuf == planes->dbuf) { + dma_buf_put(dbuf); + return 0; + } + + dba = dma_buf_attach(dbuf, ctx->dev->device); + if (IS_ERR(dba)) { + mfc_err("failed to attach dmabuf\n"); + dma_buf_put(dbuf); + return -EINVAL; + } + + sg = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL); + if (IS_ERR(sg)) { + dma_buf_detach(dbuf, dba); + dma_buf_put(dbuf); + return PTR_ERR(sg); + } + dba->priv = sg; + + planes->dbuf = dbuf; + planes->mem_priv = dba; + + *dma_addr = sg_dma_address(sg->sgl); + + return 0; +} + +static int mfc_dqbuf_dmabuf(struct mfc_inst_ctx *ctx, struct vb2_plane *plane) +{ + + struct sg_table *sg; + struct dma_buf_attachment *dba; + + dba = plane->mem_priv; + sg = dba->priv; + + dma_buf_unmap_attachment(dba, sg, DMA_FROM_DEVICE); + + return 0; +} +#endif + static int mfc_encoding_frame(struct mfc_inst_ctx *ctx, struct mfc_enc_exe_arg *exe_arg) { int ret; @@ -1597,6 +1685,9 @@ static int mfc_encoding_frame(struct mfc_inst_ctx *ctx, struct mfc_enc_exe_arg * void *ump_handle; #endif struct mfc_enc_ctx *enc_ctx = (struct mfc_enc_ctx *)ctx->c_priv; +#ifdef CONFIG_SLP_DMABUF + dma_addr_t dma_addr[MFC_NUM_PLANE]; +#endif /* Set Frame Tag */ write_shm(ctx, exe_arg->in_frametag, SET_FRAME_TAG); @@ -1648,6 +1739,39 @@ static int mfc_encoding_frame(struct mfc_inst_ctx *ctx, struct mfc_enc_exe_arg * #endif /* Set current frame buffer addr */ +#ifdef CONFIG_SLP_DMABUF + if (exe_arg->memory_type == MEMORY_DMABUF) { + ret = mfc_qbuf_dmabuf(ctx, ctx->enc_planes[0], + exe_arg->in_Y_addr, &dma_addr[0]); + if (ret) { + mfc_err("mfc_qbuf_dmabuf Y error!!! ret = %d\n", ret); + return -EINVAL; + } + ret = mfc_qbuf_dmabuf(ctx, ctx->enc_planes[1], + exe_arg->in_CbCr_addr, &dma_addr[1]); + if (ret) { + mfc_err("mfc_qbuf_dmabuf CbCr error!!! ret = %d\n", + ret); + ret = mfc_dqbuf_dmabuf(ctx, ctx->enc_planes[0]); + if (ret) + mfc_err("mfc_dqbuf_dmabuf Y error!! ret = %d\n", + ret); + return -EINVAL; + } + } + +#if (MFC_MAX_MEM_PORT_NUM == 2) + write_reg((dma_addr[0] - mfc_mem_base(1)) >> 11, + MFC_ENC_SI_CH1_CUR_Y_ADR); + write_reg((dma_addr[1] - mfc_mem_base(1)) >> 11, + MFC_ENC_SI_CH1_CUR_C_ADR); +#else + write_reg((dma_addr[0] - mfc_mem_base(0)) >> 11, + MFC_ENC_SI_CH1_CUR_Y_ADR); + write_reg((dma_addr[1] - mfc_mem_base(0)) >> 11, + MFC_ENC_SI_CH1_CUR_C_ADR); +#endif +#else #if (MFC_MAX_MEM_PORT_NUM == 2) write_reg((exe_arg->in_Y_addr - mfc_mem_base(1)) >> 11, MFC_ENC_SI_CH1_CUR_Y_ADR); write_reg((exe_arg->in_CbCr_addr - mfc_mem_base(1)) >> 11, MFC_ENC_SI_CH1_CUR_C_ADR); @@ -1655,6 +1779,7 @@ static int mfc_encoding_frame(struct mfc_inst_ctx *ctx, struct mfc_enc_exe_arg * write_reg((exe_arg->in_Y_addr - mfc_mem_base(0)) >> 11, MFC_ENC_SI_CH1_CUR_Y_ADR); write_reg((exe_arg->in_CbCr_addr - mfc_mem_base(0)) >> 11, MFC_ENC_SI_CH1_CUR_C_ADR); #endif +#endif #if 0 write_reg(1, MFC_ENC_STR_BF_U_EMPTY); @@ -1680,8 +1805,33 @@ static int mfc_encoding_frame(struct mfc_inst_ctx *ctx, struct mfc_enc_exe_arg * exe_arg->out_encoded_size = read_reg(MFC_ENC_SI_STRM_SIZE); /* FIXME: port must be checked */ - exe_arg->out_Y_addr = mfc_mem_addr_ofs(read_reg(MFC_ENCODED_Y_ADDR) << 11, 1); - exe_arg->out_CbCr_addr = mfc_mem_addr_ofs(read_reg(MFC_ENCODED_C_ADDR) << 11, 1); +#ifdef CONFIG_SLP_DMABUF + if (exe_arg->memory_type == MEMORY_DMABUF) { + exe_arg->out_Y_addr = + mfc_get_buf_dmabuf(mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_Y_ADDR) << 11, 1)); + if (exe_arg->out_Y_addr < 0) { + mfc_err("mfc_get_buf_dmabuf : Get Y fd error %d\n", + exe_arg->out_Y_addr); + return MFC_ENC_EXE_ERR; + } + exe_arg->out_CbCr_addr = + mfc_get_buf_dmabuf(mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_C_ADDR) << 11, 1)); + if (exe_arg->out_CbCr_addr < 0) { + mfc_err("mfc_get_buf_dmabuf : Get CbCr fd error %d\n", + exe_arg->out_CbCr_addr); + return MFC_ENC_EXE_ERR; + } + } else { +#endif + exe_arg->out_Y_addr = mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_Y_ADDR) << 11, 1); + exe_arg->out_CbCr_addr = mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_C_ADDR) << 11, 1); +#ifdef CONFIG_SLP_DMABUF + } +#endif #if SUPPORT_SLICE_ENCODING } else { /* slice */ ret = mfc_cmd_slice_start(ctx); @@ -1699,8 +1849,35 @@ static int mfc_encoding_frame(struct mfc_inst_ctx *ctx, struct mfc_enc_exe_arg * exe_arg->out_encoded_size = enc_ctx->slicesize; /* FIXME: port must be checked */ - exe_arg->out_Y_addr = mfc_mem_addr_ofs(read_reg(MFC_ENCODED_Y_ADDR) << 11, 1); - exe_arg->out_CbCr_addr = mfc_mem_addr_ofs(read_reg(MFC_ENCODED_C_ADDR) << 11, 1); +#ifdef CONFIG_SLP_DMABUF + if (exe_arg->memory_type == MEMORY_DMABUF) { + exe_arg->out_Y_addr = + mfc_get_buf_dmabuf(mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_Y_ADDR) + << 11, 1)); + if (exe_arg->out_Y_addr < 0) { + mfc_err("mfc_get_buf_dmabuf : Get Y fd error %d\n", + exe_arg->out_Y_addr); + return MFC_ENC_EXE_ERR; + } + exe_arg->out_CbCr_addr = + mfc_get_buf_dmabuf(mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_C_ADDR) + << 11, 1)); + if (exe_arg->out_CbCr_addr < 0) { + mfc_err("mfc_get_buf_dmabuf : Get CbCr fd error %d\n", + exe_arg->out_CbCr_addr); + return MFC_ENC_EXE_ERR; + } + } else { +#endif + exe_arg->out_Y_addr = mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_Y_ADDR) << 11, 1); + exe_arg->out_CbCr_addr = mfc_mem_addr_ofs + (read_reg(MFC_ENCODED_C_ADDR) << 11, 1); +#ifdef CONFIG_SLP_DMABUF + } +#endif } } @@ -1765,6 +1942,9 @@ int mfc_exec_encoding(struct mfc_inst_ctx *ctx, union mfc_args *args) { struct mfc_enc_exe_arg *exe_arg; int ret; +#ifdef CONFIG_SLP_DMABUF + int err; +#endif /* struct mfc_enc_ctx *enc_ctx = (struct mfc_enc_ctx *)ctx->c_priv; */ @@ -1787,6 +1967,21 @@ int mfc_exec_encoding(struct mfc_inst_ctx *ctx, union mfc_args *args) mfc_set_inst_state(ctx, INST_STATE_EXE_DONE); +#ifdef CONFIG_SLP_DMABUF + if (exe_arg->memory_type == MEMORY_DMABUF) { + err = mfc_dqbuf_dmabuf(ctx, ctx->enc_planes[0]); + if (err) { + mfc_err("mfc_dqbuf_dmabuf error!!! ret = %d\n", err); + return -EINVAL; + } + err = mfc_dqbuf_dmabuf(ctx, ctx->enc_planes[1]); + if (err) { + mfc_err("mfc_dqbuf_dmabuf error!!! ret = %d\n", err); + return -EINVAL; + } + } +#endif + return ret; } diff --git a/drivers/media/video/samsung/mfc5x/mfc_enc.h b/drivers/media/video/samsung/mfc5x/mfc_enc.h index 4bca251..21a9ba6 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_enc.h +++ b/drivers/media/video/samsung/mfc5x/mfc_enc.h @@ -87,6 +87,7 @@ struct mfc_enc_h264 { unsigned int sei_gen; /* H */ struct mfc_frame_packing fp; /* H */ + unsigned int sps_pps_gen; }; int mfc_init_encoding(struct mfc_inst_ctx *ctx, union mfc_args *args); diff --git a/drivers/media/video/samsung/mfc5x/mfc_inst.c b/drivers/media/video/samsung/mfc5x/mfc_inst.c index 518fbfc..ef0d0e0 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_inst.c +++ b/drivers/media/video/samsung/mfc5x/mfc_inst.c @@ -215,6 +215,7 @@ int mfc_set_inst_cfg(struct mfc_inst_ctx *ctx, int type, void *arg) case MFC_ENC_SETCONF_HIER_P: case MFC_ENC_SETCONF_SEI_GEN: case MFC_ENC_SETCONF_FRAME_PACKING: + case MFC_ENC_SETCONF_SPS_PPS_GEN: if (ctx->c_ops->set_codec_cfg) { if ((ctx->c_ops->set_codec_cfg(ctx, type, arg)) < 0) return MFC_SET_CONF_FAIL; diff --git a/drivers/media/video/samsung/mfc5x/mfc_inst.h b/drivers/media/video/samsung/mfc5x/mfc_inst.h index e297c55..b78dd91 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_inst.h +++ b/drivers/media/video/samsung/mfc5x/mfc_inst.h @@ -15,6 +15,9 @@ #define __MFC_INST_H __FILE__ #include <linux/list.h> +#ifdef CONFIG_SLP +#include <linux/videodev2.h> +#endif #include "mfc.h" #include "mfc_interface.h" @@ -130,7 +133,7 @@ struct mfc_inst_ctx { unsigned int width; unsigned int height; volatile unsigned char *shm; - unsigned int shmofs; + long shmofs; unsigned int ctxbufofs; unsigned int ctxbufsize; unsigned int descbufofs; /* FIXME: move to decoder context */ @@ -170,6 +173,10 @@ struct mfc_inst_ctx { #if SUPPORT_SLICE_ENCODING int slice_flag; #endif +#ifdef CONFIG_SLP + struct vb2_plane *enc_planes[VIDEO_MAX_PLANES]; + struct vb2_plane *dec_planes[VIDEO_MAX_PLANES]; +#endif }; struct mfc_inst_ctx *mfc_create_inst(void); diff --git a/drivers/media/video/samsung/mfc5x/mfc_interface.h b/drivers/media/video/samsung/mfc5x/mfc_interface.h index 61116e5..6845b8a 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_interface.h +++ b/drivers/media/video/samsung/mfc5x/mfc_interface.h @@ -242,6 +242,9 @@ struct mfc_enc_exe_arg { unsigned int out_y_cookie; unsigned int out_c_cookie; #endif +#ifdef CONFIG_SLP_DMABUF + SSBSIP_MFC_MEMORY_TYPE memory_type; /* [OUT] memory type */ +#endif }; struct mfc_dec_init_arg { @@ -312,6 +315,9 @@ struct mfc_dec_exe_arg { unsigned int out_y_cookie; unsigned int out_c_cookie; #endif +#ifdef CONFIG_SLP_DMABUF + SSBSIP_MFC_MEMORY_TYPE memory_type; /* [OUT] memory type */ +#endif int out_img_width; /* [OUT] width of YUV420 frame */ int out_img_height; /* [OUT] height of YUV420 frame */ int out_buf_width; /* [OUT] width of YUV420 frame */ diff --git a/drivers/media/video/samsung/mfc5x/mfc_mem.c b/drivers/media/video/samsung/mfc5x/mfc_mem.c index bdf7148..051e4c0 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_mem.c +++ b/drivers/media/video/samsung/mfc5x/mfc_mem.c @@ -551,10 +551,23 @@ int mfc_init_mem_mgr(struct mfc_dev *dev) /* early allocator */ #if defined(CONFIG_S5P_MEM_CMA) #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION +#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0) + cma_infos[0].lower_bound = 0x5C100000; + cma_infos[0].upper_bound = 0x5F200000; + cma_infos[0].total_size = 0x03100000; + cma_infos[0].free_size = 0x03100000; + cma_infos[0].count = 1; +#else if (cma_info(&cma_infos[0], dev->device, "A")) { mfc_info("failed to get CMA info of 'mfc-secure'\n"); return -ENOMEM; } +#endif + printk(KERN_INFO "%s[%d] cma 0x%x 0x%x 0x%x 0x%x %u\n", + __func__, __LINE__, + (int)cma_infos[0].lower_bound, (int)cma_infos[0].upper_bound, + (int)cma_infos[0].total_size, (int)cma_infos[0].free_size, + cma_infos[0].count); if (cma_info(&cma_infos[1], dev->device, "B")) { mfc_info("failed to get CMA info of 'mfc-normal'\n"); @@ -598,6 +611,15 @@ int mfc_init_mem_mgr(struct mfc_dev *dev) return -ENOMEM; } +#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0) + base[0] = 0x5c100000; + dev->mem_infos[0].base = base[0]; + dev->mem_infos[0].size = size; + dev->mem_infos[0].addr = phys_to_virt(base[0]); + mfc_info("%s[%d]: base 0x%x, size 0x%x, addr 0x%x\n", + __func__, __LINE__, (int)base[0], (int)size, + (int)dev->mem_infos[0].addr); +#else base[0] = cma_alloc(dev->device, "A", size, ALIGN_128KB); if (IS_ERR_VALUE(base[0])) { mfc_err("failed to get rsv. memory from CMA on mfc-secure"); @@ -607,7 +629,7 @@ int mfc_init_mem_mgr(struct mfc_dev *dev) dev->mem_infos[0].base = base[0]; dev->mem_infos[0].size = size; dev->mem_infos[0].addr = cma_get_virt(base[0], size, 0); - +#endif available_size -= dev->mem_infos[0].size; mfc_dbg("avail: 0x%08x\n", available_size); @@ -670,7 +692,12 @@ int mfc_init_mem_mgr(struct mfc_dev *dev) size = MAX_MEM_OFFSET; } +#ifdef CONFIG_SLP + base[0] = cma_alloc(dev->device, "AB", MFC_FW_SYSTEM_SIZE, + ALIGN_128KB); +#else base[0] = cma_alloc(dev->device, "AB", size, ALIGN_128KB); +#endif if (IS_ERR_VALUE(base[0])) { mfc_err("failed to get rsv. memory from CMA"); return -ENOMEM; @@ -702,7 +729,12 @@ int mfc_init_mem_mgr(struct mfc_dev *dev) size = MAX_MEM_OFFSET; } +#ifdef CONFIG_SLP + base[0] = cma_alloc(dev->device, cma_index ? "B" : "A", + MFC_FW_SYSTEM_SIZE, ALIGN_128KB); +#else base[0] = cma_alloc(dev->device, cma_index ? "B" : "A", size, ALIGN_128KB); +#endif if (IS_ERR_VALUE(base[0])) { mfc_err("failed to get rsv. memory from CMA on port #0"); return -ENOMEM; @@ -724,7 +756,12 @@ int mfc_init_mem_mgr(struct mfc_dev *dev) size = MAX_MEM_OFFSET; } +#ifdef CONFIG_SLP + base[1] = cma_index ? cma_infos[1].lower_bound : + cma_infos[0].lower_bound; +#else base[1] = cma_alloc(dev->device, cma_index ? "B" : "A", size, ALIGN_128KB); +#endif if (IS_ERR_VALUE(base[1])) { mfc_err("failed to get rsv. memory from CMA on port #1"); cma_free(base[0]); diff --git a/drivers/media/video/samsung/mfc5x/mfc_shm.h b/drivers/media/video/samsung/mfc5x/mfc_shm.h index e5d7ba7..3da6573 100644 --- a/drivers/media/video/samsung/mfc5x/mfc_shm.h +++ b/drivers/media/video/samsung/mfc5x/mfc_shm.h @@ -66,7 +66,7 @@ enum MFC_SHM_OFS DBG_HISTORY_INPUT1 = 0x00D4, /* C */ DBG_HISTORY_OUTPUT = 0x00D8, /* C */ HIERARCHICAL_P_QP = 0x00E0, /* E, H.264 */ - HW_VERSRION = 0x010C, /* C */ + HW_VERSION = 0x010C, /* C */ SEI_ENABLE = 0x0168, /* C, H.264 */ FRAME_PACK_SEI_AVAIL = 0x016C, /* D, H.264 */ FRAME_PACK_ARRGMENT_ID = 0x0170, /* D, H.264 */ |