aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/mfc5x
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/mfc5x')
-rw-r--r--drivers/media/video/samsung/mfc5x/Kconfig12
-rw-r--r--drivers/media/video/samsung/mfc5x/SsbSipMfcApi.h19
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc.h4
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_buf.c287
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_buf.h10
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dec.c90
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dec.h5
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dev.c119
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dev.h6
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_enc.c205
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_enc.h1
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_inst.c1
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_inst.h9
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_interface.h6
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_mem.c39
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_shm.h2
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 */