aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/mfc5x/mfc_enc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/mfc5x/mfc_enc.c')
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_enc.c205
1 files changed, 200 insertions, 5 deletions
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;
}