This changes the file names more intuitively.
mfc_regs_v10.h => mfc_regs.h
mfc_reg.c/h => mfc_reg_api.c/h
mfc_cal.c/h => mfc_hw_reg_api.c/h
mfc_dec_ops.c => mfc_dec_ctrl.c
mfc_enc_ops.c => mfc_enc_ctrl.c
mfc_dec.c/h => mfc_dec_v4l2.c/h
mfc_enc.c/h => mfc_enc_v4l2.c/h
mfc_dec_vb2_ops.c => mfc_dec_vb2.c
mfc_enc_vb2_ops.c => mfc_enc_vb2.c
mfc_irq.c/h => mfc_isr.c/h
Change-Id: Ie217f5ccead5ab12888ec3fe83c292be10a0f553
Signed-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
obj-$(CONFIG_VIDEO_EXYNOS_MFC) := exynos_mfc.o
-exynos_mfc-y += mfc.o mfc_irq.o mfc_dec.o mfc_dec_vb2_ops.o mfc_enc.o mfc_enc_vb2_ops.o
+exynos_mfc-y += mfc.o mfc_isr.o mfc_dec_v4l2.o mfc_dec_vb2.o mfc_enc_v4l2.o mfc_enc_vb2.o
exynos_mfc-y += mfc_ctrl.o mfc_hwlock.o mfc_nal_q.o mfc_watchdog.o mfc_opr.o mfc_sync.o
-exynos_mfc-y += mfc_pm.o mfc_inst.o mfc_cmd.o mfc_cal.o mfc_reg.o mfc_perf_measure.o
-exynos_mfc-y += mfc_dec_ops.o mfc_enc_ops.o mfc_enc_param.o
+exynos_mfc-y += mfc_pm.o mfc_inst.o mfc_cmd.o mfc_hw_reg_api.o mfc_reg_api.o mfc_perf_measure.o
+exynos_mfc-y += mfc_dec_ctrl.o mfc_enc_ctrl.o mfc_enc_param.o
exynos_mfc-y += mfc_queue.o mfc_buf.o mfc_utils.o mfc_qos.o mfc_mem.o
exynos_mfc-y += mfc_debugfs.o mfc_otf.o
exynos_mfc-y += mfc_mmcache.o
#include "mfc_common.h"
-#include "mfc_irq.h"
-#include "mfc_dec.h"
-#include "mfc_enc.h"
+#include "mfc_isr.h"
+#include "mfc_dec_v4l2.h"
+#include "mfc_enc_v4l2.h"
#include "mfc_ctrl.h"
#include "mfc_hwlock.h"
#include "mfc_inst.h"
#include "mfc_pm.h"
-#include "mfc_cal.h"
#include "mfc_perf_measure.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_mmcache.h"
#include "mfc_qos.h"
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_cal.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <trace/events/mfc.h>
-
-#include "mfc_cal.h"
-#include "mfc_pm.h"
-
-/* Reset the device */
-int mfc_reset_mfc(struct mfc_dev *dev)
-{
- int i;
-
- mfc_debug_enter();
-
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
-
- /* Zero Initialization of MFC registers */
- MFC_WRITEL(0, MFC_REG_RISC2HOST_CMD);
- MFC_WRITEL(0, MFC_REG_HOST2RISC_CMD);
- MFC_WRITEL(0, MFC_REG_FW_VERSION);
-
- for (i = 0; i < MFC_REG_REG_CLEAR_COUNT; i++)
- MFC_WRITEL(0, MFC_REG_REG_CLEAR_BEGIN + (i*4));
-
- MFC_WRITEL(0x1FFF, MFC_REG_MFC_RESET);
- MFC_WRITEL(0, MFC_REG_MFC_RESET);
-
- mfc_debug_leave();
-
- return 0;
-}
-
-void mfc_set_risc_base_addr(struct mfc_dev *dev,
- enum mfc_buf_usage_type buf_type)
-{
- struct mfc_special_buf *fw_buf;
-
- fw_buf = &dev->fw_buf;
-
- if (buf_type == MFCBUF_DRM)
- fw_buf = &dev->drm_fw_buf;
-
- MFC_WRITEL(fw_buf->daddr, MFC_REG_RISC_BASE_ADDRESS);
- mfc_debug(2, "[MEMINFO][F/W] %s Base Address : %#x\n",
- buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
- MFC_TRACE_DEV("%s F/W Base Address : %#x\n",
- buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
-}
-
-void mfc_cmd_host2risc(struct mfc_dev *dev, int cmd)
-{
- mfc_debug(1, "Issue the command: %d\n", cmd);
- MFC_TRACE_DEV(">> CMD : %d, (dev:0x%lx, bits:%lx, owned:%d, wl:%d, trans:%d)\n",
- cmd, dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
- dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
- trace_mfc_frame_start(dev->curr_ctx, cmd, 0, 0);
- /* Reset RISC2HOST command except nal q stop command */
- if (cmd != MFC_REG_H2R_CMD_STOP_QUEUE)
- MFC_WRITEL(0x0, MFC_REG_RISC2HOST_CMD);
-
- /* Start the timeout watchdog */
- if ((cmd != MFC_REG_H2R_CMD_NAL_QUEUE) && (cmd != MFC_REG_H2R_CMD_STOP_QUEUE))
- mfc_watchdog_start_tick(dev);
-
- if (dbg_enable) {
- /* For FW debugging */
- mfc_dbg_set_addr(dev);
- mfc_dbg_enable(dev);
- }
-
- /* Issue the command */
- MFC_WRITEL(cmd, MFC_REG_HOST2RISC_CMD);
- MFC_WRITEL(0x1, MFC_REG_HOST2RISC_INT);
-}
-
-/* Check whether HW interrupt has occurred or not */
-int mfc_check_risc2host(struct mfc_dev *dev)
-{
- if (mfc_pm_get_pwr_ref_cnt(dev) && mfc_pm_get_clk_ref_cnt(dev)) {
- if (MFC_READL(MFC_REG_RISC2HOST_INT))
- return MFC_READL(MFC_REG_RISC2HOST_CMD);
- else
- return 0;
- }
-
- return 0;
-}
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_cal.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MFC_CAL_H
-#define __MFC_CAL_H __FILE__
-
-#include "mfc_reg.h"
-
-#include "mfc_common.h"
-
-#include "mfc_utils.h"
-
-
-#define mfc_get_int_reason() (MFC_READL(MFC_REG_RISC2HOST_CMD) \
- & MFC_REG_RISC2HOST_CMD_MASK)
-#define mfc_clear_int_sfr() \
- do { \
- MFC_WRITEL(0, MFC_REG_RISC2HOST_CMD); \
- MFC_WRITEL(0, MFC_REG_RISC2HOST_INT); \
- } while (0)
-
-static inline int mfc_stop_bus(struct mfc_dev *dev)
-{
- unsigned int status;
- unsigned long timeout;
-
- /* Reset */
- MFC_WRITEL(0x1, MFC_REG_MFC_BUS_RESET_CTRL);
-
- timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
- /* Check bus status */
- do {
- if (time_after(jiffies, timeout)) {
- mfc_err_dev("Timeout while resetting MFC.\n");
- return -EIO;
- }
- status = MFC_READL(MFC_REG_MFC_BUS_RESET_CTRL);
- } while ((status & 0x2) == 0);
-
- return 0;
-}
-
-static inline void mfc_start_bus(struct mfc_dev *dev)
-{
- int val;
-
- val = MFC_READL(MFC_REG_MFC_BUS_RESET_CTRL);
- val &= ~(0x1);
- MFC_WRITEL(val, MFC_REG_MFC_BUS_RESET_CTRL);
-}
-
-static inline void mfc_risc_on(struct mfc_dev *dev)
-{
- mfc_clean_dev_int_flags(dev);
-
- MFC_WRITEL(0x1, MFC_REG_RISC_ON);
- MFC_WRITEL(0x0, MFC_REG_MFC_OFF);
- mfc_debug(1, "RISC_ON\n");
- MFC_TRACE_DEV(">> RISC ON\n");
-}
-
-static inline void mfc_risc_off(struct mfc_dev *dev)
-{
- unsigned int status;
- unsigned long timeout;
-
- timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
- /* Check pending status */
- do {
- if (time_after(jiffies, timeout)) {
- mfc_err_dev("Timeout while pendng clear\n");
- mfc_err_dev("MFC access pending state: %#x\n", status);
- mfc_err_dev("MFC access pending R: %#x, W: %#x\n",
- MFC_READL(MFC_REG_MFC_RPEND),
- MFC_READL(MFC_REG_MFC_WPEND));
- break;
- }
- status = MFC_READL(MFC_REG_MFC_BUS_STATUS);
- } while (status != 0);
-
- MFC_WRITEL(0x0, MFC_REG_RISC_ON);
-}
-
-static inline void mfc_mfc_off(struct mfc_dev *dev)
-{
- mfc_info_dev("MFC h/w state: %d\n",
- MFC_READL(MFC_REG_MFC_STATE) & 0x7);
- MFC_WRITEL(0x1, MFC_REG_MFC_OFF);
-}
-
-static inline void mfc_enable_all_clocks(struct mfc_dev *dev)
-{
- /* Enable all FW clock gating */
- MFC_WRITEL(0xFFFFFFFF, MFC_REG_MFC_FW_CLOCK);
-}
-
-int mfc_reset_mfc(struct mfc_dev *dev);
-void mfc_set_risc_base_addr(struct mfc_dev *dev,
- enum mfc_buf_usage_type buf_type);
-void mfc_cmd_host2risc(struct mfc_dev *dev, int cmd);
-int mfc_check_risc2host(struct mfc_dev *dev);
-
-#endif /* __MFC_CAL_H */
#include "mfc_cmd.h"
-#include "mfc_cal.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_mmcache.h"
#include "mfc_utils.h"
#include <media/videobuf2-dma-sg.h>
#include <asm/cacheflush.h>
-#include "mfc_regs_v10.h"
+#include "mfc_regs.h"
#include "mfc_macros.h"
#include "mfc_debug.h"
#include "exynos_mfc_media.h"
#include "mfc_pm.h"
#include "mfc_cmd.h"
-#include "mfc_cal.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_utils.h"
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_dec.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_dec.h"
-#include "mfc_dec_internal.h"
-
-#include "mfc_hwlock.h"
-#include "mfc_opr.h"
-#include "mfc_sync.h"
-#include "mfc_mmcache.h"
-
-#include "mfc_qos.h"
-#include "mfc_queue.h"
-#include "mfc_utils.h"
-#include "mfc_buf.h"
-#include "mfc_mem.h"
-
-#define MAX_FRAME_SIZE (2*1024*1024)
-
-/* Find selected format description */
-static struct mfc_fmt *__mfc_dec_find_format(struct mfc_ctx *ctx,
- unsigned int pixelformat)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_fmt *fmt = NULL;
- unsigned long i;
-
- for (i = 0; i < NUM_FORMATS; i++) {
- if (dec_formats[i].fourcc == pixelformat) {
- fmt = (struct mfc_fmt *)&dec_formats[i];
- break;
- }
- }
-
- if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
- mfc_err_ctx("[FRAME] 10bit is not supported\n");
- fmt = NULL;
- }
- if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
- mfc_err_ctx("[FRAME] 422 is not supported\n");
- fmt = NULL;
- }
-
- return fmt;
-}
-
-static struct v4l2_queryctrl *__mfc_dec_get_ctrl(int id)
-{
- unsigned long i;
-
- for (i = 0; i < NUM_CTRLS; ++i)
- if (id == controls[i].id)
- return &controls[i];
-
- return NULL;
-}
-
-/* Check whether a ctrl value if correct */
-static int __mfc_dec_check_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct v4l2_queryctrl *c;
-
- c = __mfc_dec_get_ctrl(ctrl->id);
- if (!c) {
- mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
- return -EINVAL;
- }
-
- if (ctrl->value < c->minimum || ctrl->value > c->maximum
- || (c->step != 0 && ctrl->value % c->step != 0)) {
- mfc_err_ctx("[CTRLS] Invalid control value (%#x)\n", ctrl->value);
- return -ERANGE;
- }
-
- return 0;
-}
-
-/* Query capabilities of the device */
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
- strncpy(cap->card, "decoder", sizeof(cap->card) - 1);
- cap->bus_info[0] = 0;
- cap->version = KERNEL_VERSION(1, 0, 0);
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
- | V4L2_CAP_VIDEO_OUTPUT
- | V4L2_CAP_VIDEO_CAPTURE_MPLANE
- | V4L2_CAP_VIDEO_OUTPUT_MPLANE
- | V4L2_CAP_STREAMING
- | V4L2_CAP_DEVICE_CAPS;
-
- cap->capabilities = cap->device_caps;
-
- return 0;
-}
-
-static int __mfc_dec_enum_fmt(struct mfc_dev *dev, struct v4l2_fmtdesc *f,
- unsigned int type)
-{
- struct mfc_fmt *fmt;
- unsigned long i, j = 0;
-
- for (i = 0; i < NUM_FORMATS; ++i) {
- if (!(dec_formats[i].type & type))
- continue;
- if (!dev->pdata->support_10bit && (dec_formats[i].type & MFC_FMT_10BIT))
- continue;
- if (!dev->pdata->support_422 && (dec_formats[i].type & MFC_FMT_422))
- continue;
-
- if (j == f->index) {
- fmt = &dec_formats[i];
- strlcpy(f->description, fmt->name,
- sizeof(f->description));
- f->pixelformat = fmt->fourcc;
-
- return 0;
- }
-
- ++j;
- }
-
- return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
- struct v4l2_fmtdesc *f)
-{
- struct mfc_dev *dev = video_drvdata(file);
-
- return __mfc_dec_enum_fmt(dev, f, MFC_FMT_FRAME);
-}
-
-static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
- struct v4l2_fmtdesc *f)
-{
- struct mfc_dev *dev = video_drvdata(file);
-
- return __mfc_dec_enum_fmt(dev, f, MFC_FMT_STREAM);
-}
-
-static void __mfc_dec_change_format(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- u32 org_fmt = ctx->dst_fmt->fourcc;
-
- if (ctx->is_10bit && ctx->is_422) {
- switch (org_fmt) {
- case V4L2_PIX_FMT_NV16M_S10B:
- case V4L2_PIX_FMT_NV61M_S10B:
- case V4L2_PIX_FMT_NV16M_P210:
- case V4L2_PIX_FMT_NV61M_P210:
- /* It is right format */
- break;
- case V4L2_PIX_FMT_NV12M:
- case V4L2_PIX_FMT_NV16M:
- case V4L2_PIX_FMT_NV12M_S10B:
- case V4L2_PIX_FMT_NV12M_P010:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
- break;
- case V4L2_PIX_FMT_NV21M:
- case V4L2_PIX_FMT_NV61M:
- case V4L2_PIX_FMT_NV21M_S10B:
- case V4L2_PIX_FMT_NV21M_P010:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M_S10B);
- break;
- default:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
- break;
- }
- ctx->raw_buf.num_planes = 2;
- } else if (ctx->is_10bit && !ctx->is_422) {
- if (ctx->dst_fmt->mem_planes == 1) {
- /* YUV420 only supports the single plane */
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12N_10B);
- } else {
- switch (org_fmt) {
- case V4L2_PIX_FMT_NV12M_S10B:
- case V4L2_PIX_FMT_NV21M_S10B:
- case V4L2_PIX_FMT_NV12M_P010:
- case V4L2_PIX_FMT_NV21M_P010:
- /* It is right format */
- break;
- case V4L2_PIX_FMT_NV12M:
- case V4L2_PIX_FMT_NV16M:
- case V4L2_PIX_FMT_NV16M_S10B:
- case V4L2_PIX_FMT_NV16M_P210:
- if (dev->pdata->P010_decoding)
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
- else
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
- break;
- case V4L2_PIX_FMT_NV21M:
- case V4L2_PIX_FMT_NV61M:
- case V4L2_PIX_FMT_NV61M_S10B:
- case V4L2_PIX_FMT_NV61M_P210:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M_S10B);
- break;
- default:
- if (dev->pdata->P010_decoding)
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
- else
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
- break;
- }
- }
- ctx->raw_buf.num_planes = 2;
- } else if (!ctx->is_10bit && ctx->is_422) {
- switch (org_fmt) {
- case V4L2_PIX_FMT_NV16M:
- case V4L2_PIX_FMT_NV61M:
- /* It is right format */
- break;
- case V4L2_PIX_FMT_NV12M:
- case V4L2_PIX_FMT_NV12M_S10B:
- case V4L2_PIX_FMT_NV16M_S10B:
- case V4L2_PIX_FMT_NV12M_P010:
- case V4L2_PIX_FMT_NV16M_P210:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
- break;
- case V4L2_PIX_FMT_NV21M:
- case V4L2_PIX_FMT_NV21M_S10B:
- case V4L2_PIX_FMT_NV61M_S10B:
- case V4L2_PIX_FMT_NV21M_P010:
- case V4L2_PIX_FMT_NV61M_P210:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M);
- break;
- default:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
- break;
- }
- ctx->raw_buf.num_planes = 2;
- } else {
- /* YUV420 8bit */
- switch (org_fmt) {
- case V4L2_PIX_FMT_NV16M:
- case V4L2_PIX_FMT_NV12M_S10B:
- case V4L2_PIX_FMT_NV16M_S10B:
- case V4L2_PIX_FMT_NV12M_P010:
- case V4L2_PIX_FMT_NV16M_P210:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M);
- break;
- case V4L2_PIX_FMT_NV61M:
- case V4L2_PIX_FMT_NV21M_S10B:
- case V4L2_PIX_FMT_NV61M_S10B:
- case V4L2_PIX_FMT_NV21M_P010:
- case V4L2_PIX_FMT_NV61M_P210:
- ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M);
- break;
- default:
- /* It is right format */
- break;
- }
- }
-
- if (org_fmt != ctx->dst_fmt->fourcc)
- mfc_info_ctx("[FRAME] format is changed to %s\n", ctx->dst_fmt->name);
-}
-
-/* Get format */
-static int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
- struct mfc_raw_info *raw;
- int i;
-
- mfc_debug_enter();
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- mfc_debug(2, "dec dst g_fmt, state: %d\n", ctx->state);
-
- if (ctx->state == MFCINST_GOT_INST ||
- ctx->state == MFCINST_RES_CHANGE_FLUSH ||
- ctx->state == MFCINST_RES_CHANGE_END) {
- /* If the MFC is parsing the header,
- * so wait until it is finished */
- if (mfc_wait_for_done_ctx(ctx,
- MFC_REG_R2H_CMD_SEQ_DONE_RET)) {
- mfc_err_dev("header parsing failed\n");
- return -EAGAIN;
- }
- }
-
- if (ctx->state >= MFCINST_HEAD_PARSED &&
- ctx->state < MFCINST_ABORT) {
- /* This is run on CAPTURE (deocde output) */
-
- /* only NV16(61) format is supported for 422 format */
- /* only 2 plane is supported for 10bit */
- __mfc_dec_change_format(ctx);
-
- raw = &ctx->raw_buf;
- /* Width and height are set to the dimensions
- of the movie, the buffer is bigger and
- further processing stages should crop to this
- rectangle. */
- mfc_dec_calc_dpb_size(ctx);
-
- if (IS_LOW_MEM) {
- unsigned int dpb_size;
- /*
- * If total memory requirement is too big for this device,
- * then it returns error.
- * DPB size : Total plane size * the number of DPBs
- * 5: the number of extra DPBs
- * 3: the number of DPBs for Android framework
- * 600MB: being used to return an error,
- * when 8K resolution video clip is being tried to be decoded
- */
- dpb_size = (ctx->raw_buf.total_plane_size * (ctx->dpb_count + 5 + 3));
- if (dpb_size > SZ_600M) {
- mfc_info_ctx("required memory size is too big (%dx%d, dpb: %d)\n",
- ctx->img_width, ctx->img_height, ctx->dpb_count);
- return -EINVAL;
- }
- }
-
- pix_fmt_mp->width = ctx->img_width;
- pix_fmt_mp->height = ctx->img_height;
- pix_fmt_mp->num_planes = ctx->dst_fmt->mem_planes;
-
- if (dec->is_interlaced)
- pix_fmt_mp->field = V4L2_FIELD_INTERLACED;
- else
- pix_fmt_mp->field = V4L2_FIELD_NONE;
-
- /* Set pixelformat to the format in which MFC
- outputs the decoded frame */
- pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
- for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
- pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
- if (ctx->dst_fmt->mem_planes == 1) {
- pix_fmt_mp->plane_fmt[i].sizeimage = raw->total_plane_size;
- } else {
- if (ctx->is_10bit)
- pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i]
- + raw->plane_size_2bits[i];
- else
- pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
- }
- }
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int vidioc_g_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
- mfc_debug_enter();
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- mfc_debug(4, "dec src g_fmt, state: %d\n", ctx->state);
-
- /* This is run on OUTPUT
- The buffer contains compressed image
- so width and height have no meaning */
- pix_fmt_mp->width = 0;
- pix_fmt_mp->height = 0;
- pix_fmt_mp->field = V4L2_FIELD_NONE;
- pix_fmt_mp->plane_fmt[0].bytesperline = dec->src_buf_size;
- pix_fmt_mp->plane_fmt[0].sizeimage = dec->src_buf_size;
- pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
- pix_fmt_mp->num_planes = ctx->src_fmt->mem_planes;
-
- mfc_debug_leave();
-
- return 0;
-}
-
-/* Try format */
-static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_fmt *fmt;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
- fmt = __mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
- if (!fmt) {
- mfc_err_dev("Unsupported format for %s\n",
- V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* Set format */
-static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
- mfc_debug_enter();
-
- if (ctx->vq_dst.streaming) {
- mfc_err_ctx("queue busy\n");
- return -EBUSY;
- }
-
- ctx->dst_fmt = __mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
- if (!ctx->dst_fmt) {
- mfc_err_ctx("Unsupported format for destination\n");
- return -EINVAL;
- }
- ctx->raw_buf.num_planes = ctx->dst_fmt->num_planes;
- mfc_info_ctx("[FRAME] dec dst pixelformat : %s\n", ctx->dst_fmt->name);
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int __mfc_force_close_inst(struct mfc_dev *dev, struct mfc_ctx *ctx)
-{
- if (ctx->inst_no == MFC_NO_INSTANCE_SET)
- return 0;
-
- mfc_change_state(ctx, MFCINST_RETURN_INST);
- mfc_set_bit(ctx->num, &dev->work_bits);
- mfc_clean_ctx_int_flags(ctx);
- if (mfc_just_run(dev, ctx->num)) {
- mfc_err_ctx("Failed to run MFC\n");
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- return -EIO;
- }
-
- /* Wait until instance is returned or timeout occured */
- if (mfc_wait_for_done_ctx(ctx,
- MFC_REG_R2H_CMD_CLOSE_INSTANCE_RET)) {
- mfc_err_ctx("Waiting for CLOSE_INSTANCE timed out\n");
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- return -EIO;
- }
-
- /* Free resources */
- mfc_release_instance_context(ctx);
- mfc_change_state(ctx, MFCINST_INIT);
-
- return 0;
-}
-
-static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mfc_dev *dev = video_drvdata(file);
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec = ctx->dec_priv;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
- int ret = 0;
-
- mfc_debug_enter();
-
- if (ctx->vq_src.streaming) {
- mfc_err_ctx("queue busy\n");
- return -EBUSY;
- }
-
- ctx->src_fmt = __mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
- if (!ctx->src_fmt) {
- mfc_err_ctx("Unsupported format for source\n");
- return -EINVAL;
- }
-
- ctx->codec_mode = ctx->src_fmt->codec_mode;
- mfc_info_ctx("[STREAM] Dec src codec(%d): %s\n",
- ctx->codec_mode, ctx->src_fmt->name);
-
- ctx->pix_format = pix_fmt_mp->pixelformat;
- if ((pix_fmt_mp->width > 0) && (pix_fmt_mp->height > 0)) {
- ctx->img_height = pix_fmt_mp->height;
- ctx->img_width = pix_fmt_mp->width;
- }
-
- /* As this buffer will contain compressed data, the size is set
- * to the maximum size. */
- if (pix_fmt_mp->plane_fmt[0].sizeimage)
- dec->src_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
- else
- dec->src_buf_size = MAX_FRAME_SIZE;
- mfc_debug(2, "[STREAM] sizeimage: %d\n", pix_fmt_mp->plane_fmt[0].sizeimage);
- pix_fmt_mp->plane_fmt[0].bytesperline = 0;
-
- MFC_TRACE_CTX_HWLOCK("**DEC s_fmt\n");
- ret = mfc_get_hwlock_ctx(ctx);
- if (ret < 0) {
- mfc_err_ctx("Failed to get hwlock\n");
- return -EBUSY;
- }
-
- /* In case of calling s_fmt twice or more */
- ret = __mfc_force_close_inst(dev, ctx);
- if (ret) {
- mfc_err_ctx("Failed to close already opening instance\n");
- return -EIO;
- }
-
- ret = mfc_alloc_instance_context(ctx);
- if (ret) {
- mfc_err_ctx("Failed to allocate dec instance[%d] buffers\n",
- ctx->num);
- mfc_release_hwlock_ctx(ctx);
- return -ENOMEM;
- }
-
- mfc_set_bit(ctx->num, &dev->work_bits);
- ret = mfc_just_run(dev, ctx->num);
- if (ret) {
- mfc_err_ctx("Failed to run MFC\n");
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- mfc_release_instance_context(ctx);
- return -EIO;
- }
-
- if (mfc_wait_for_done_ctx(ctx,
- MFC_REG_R2H_CMD_OPEN_INSTANCE_RET)) {
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- mfc_release_instance_context(ctx);
- return -EIO;
- }
-
- mfc_release_hwlock_ctx(ctx);
-
- mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
-
- if (mfc_dec_ctx_ready(ctx))
- mfc_set_bit(ctx->num, &dev->work_bits);
- if (mfc_is_work_to_do(dev))
- queue_work(dev->butler_wq, &dev->butler_work);
-
- mfc_debug_leave();
-
- return 0;
-}
-
-/* Reqeust buffers */
-static int vidioc_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *reqbufs)
-{
- struct mfc_dev *dev = video_drvdata(file);
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec;
- int ret = 0;
-
- mfc_debug_enter();
-
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- if (reqbufs->memory == V4L2_MEMORY_MMAP) {
- mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
- return -EINVAL;
- }
-
- if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src reqbuf(%d)\n", reqbufs->count);
- /* Can only request buffers after
- an instance has been opened.*/
- if (ctx->state == MFCINST_GOT_INST) {
- if (reqbufs->count == 0) {
- ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
- ctx->output_state = QUEUE_FREE;
- return ret;
- }
-
- /* Decoding */
- if (ctx->output_state != QUEUE_FREE) {
- mfc_err_ctx("Bufs have already been requested\n");
- return -EINVAL;
- }
-
- ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
- if (ret) {
- mfc_err_ctx("vb2_reqbufs on src failed\n");
- return ret;
- }
-
- ctx->output_state = QUEUE_BUFS_REQUESTED;
- }
- } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "dec dst reqbuf(%d)\n", reqbufs->count);
- if (reqbufs->count == 0) {
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-
- if (dev->has_mmcache && dev->mmcache.is_on_status)
- mfc_invalidate_mmcache(dev);
-
- mfc_release_codec_buffers(ctx);
- ctx->capture_state = QUEUE_FREE;
- return ret;
- }
-
- dec->dst_memtype = reqbufs->memory;
-
- if (ctx->capture_state != QUEUE_FREE) {
- mfc_err_ctx("Bufs have already been requested\n");
- return -EINVAL;
- }
-
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- if (ret) {
- mfc_err_ctx("vb2_reqbufs on capture failed\n");
- return ret;
- }
-
- if (reqbufs->count < ctx->dpb_count) {
- mfc_err_ctx("Not enough buffers allocated\n");
- reqbufs->count = 0;
- vb2_reqbufs(&ctx->vq_dst, reqbufs);
- return -ENOMEM;
- }
-
- dec->total_dpb_count = reqbufs->count;
-
- ret = mfc_alloc_codec_buffers(ctx);
- if (ret) {
- mfc_err_ctx("Failed to allocate decoding buffers\n");
- reqbufs->count = 0;
- vb2_reqbufs(&ctx->vq_dst, reqbufs);
- return -ENOMEM;
- }
-
- ctx->capture_state = QUEUE_BUFS_REQUESTED;
-
- if (mfc_dec_ctx_ready(ctx))
- mfc_set_bit(ctx->num, &dev->work_bits);
-
- mfc_try_run(dev);
- }
-
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Query buffer */
-static int vidioc_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret;
-
- mfc_debug_enter();
-
- if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "dec dst querybuf, state: %d\n", ctx->state);
- ret = vb2_querybuf(&ctx->vq_dst, buf);
- if (ret != 0) {
- mfc_err_dev("dec dst: error in vb2_querybuf()\n");
- return ret;
- }
- } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src querybuf, state: %d\n", ctx->state);
- ret = vb2_querybuf(&ctx->vq_src, buf);
- if (ret != 0) {
- mfc_err_dev("dec src: error in vb2_querybuf()\n");
- return ret;
- }
- } else {
- mfc_err_dev("invalid buf type (%d)\n", buf->type);
- return -EINVAL;
- }
-
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Queue a buffer */
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = -EINVAL;
-
- mfc_debug_enter();
-
- if (ctx->state == MFCINST_ERROR) {
- mfc_err_ctx("Call on QBUF after unrecoverable error\n");
- return -EIO;
- }
-
- if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
- mfc_err_ctx("multiplanar but length is zero\n");
- return -EIO;
- }
-
- if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src buf[%d] Q\n", buf->index);
- if (buf->m.planes[0].bytesused > buf->m.planes[0].length) {
- mfc_err_ctx("data size (%d) must be less than "
- "buffer size(%d)\n",
- buf->m.planes[0].bytesused,
- buf->m.planes[0].length);
- return -EIO;
- }
-
- mfc_qos_update_framerate(ctx);
-
- if (!buf->m.planes[0].bytesused) {
- buf->m.planes[0].bytesused = buf->m.planes[0].length;
- mfc_debug(2, "Src size zero, changed to buf size %d\n",
- buf->m.planes[0].bytesused);
- } else {
- mfc_debug(2, "Src size = %d\n", buf->m.planes[0].bytesused);
- }
- ret = vb2_qbuf(&ctx->vq_src, buf);
- } else {
- mfc_debug(4, "dec dst buf[%d] Q\n", buf->index);
- ret = vb2_qbuf(&ctx->vq_dst, buf);
- }
-
- mfc_debug_leave();
- return ret;
-}
-
-/* Dequeue a buffer */
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec = ctx->dec_priv;
- struct dec_dpb_ref_info *dstBuf, *srcBuf;
- int ret;
- int ncount = 0;
-
- mfc_debug_enter();
-
- if (ctx->state == MFCINST_ERROR) {
- mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
- return -EIO;
- }
- if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src buf[%d] DQ\n", buf->index);
- ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
- } else {
- mfc_debug(4, "dec dst buf[%d] DQ\n", buf->index);
- ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-
- if (buf->index >= MFC_MAX_DPBS) {
- mfc_err_ctx("buffer index[%d] range over\n", buf->index);
- return -EINVAL;
- }
-
- /* Memcpy from dec->ref_info to shared memory */
- srcBuf = &dec->ref_info[buf->index];
- for (ncount = 0; ncount < MFC_MAX_DPBS; ncount++) {
- if (srcBuf->dpb[ncount].fd[0] == MFC_INFO_INIT_FD)
- break;
- mfc_debug(2, "[DPB] DQ index[%d] Released FD = %d\n",
- buf->index, srcBuf->dpb[ncount].fd[0]);
- }
-
- if (dec->sh_handle.vaddr != NULL) {
- dstBuf = (struct dec_dpb_ref_info *)
- dec->sh_handle.vaddr + buf->index;
- memcpy(dstBuf, srcBuf, sizeof(struct dec_dpb_ref_info));
- dstBuf->index = buf->index;
- }
- }
- mfc_debug_leave();
- return ret;
-}
-
-/* Stream on */
-static int vidioc_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = -EINVAL;
-
- mfc_debug_enter();
-
- if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src streamon\n");
- ret = vb2_streamon(&ctx->vq_src, type);
- } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "dec dst streamon\n");
- ret = vb2_streamon(&ctx->vq_dst, type);
-
- if (!ret)
- mfc_qos_on(ctx);
- } else {
- mfc_err_ctx("unknown v4l2 buffer type\n");
- }
-
- mfc_debug(2, "src: %d, dst: %d, state = %d, dpb_count = %d\n",
- mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
- mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
- ctx->state, ctx->dpb_count);
-
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Stream off, which equals to a pause */
-static int vidioc_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = -EINVAL;
-
- mfc_debug_enter();
-
- if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src streamoff\n");
- mfc_qos_reset_last_framerate(ctx);
-
- ret = vb2_streamoff(&ctx->vq_src, type);
- } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "dec dst streamoff\n");
- ret = vb2_streamoff(&ctx->vq_dst, type);
- if (!ret)
- mfc_qos_off(ctx);
- } else {
- mfc_err_ctx("unknown v4l2 buffer type\n");
- }
-
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Query a ctrl */
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct v4l2_queryctrl *c;
-
- c = __mfc_dec_get_ctrl(qc->id);
- if (!c) {
- mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
- return -EINVAL;
- }
-
- *qc = *c;
- return 0;
-}
-
-static int __mfc_dec_ext_info(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- int val = 0;
-
- val |= DEC_SET_DYNAMIC_DPB;
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
- val |= DEC_SET_SKYPE_FLAG;
-
- mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
-
- return val;
-}
-
-/* Get ctrl */
-static int __mfc_dec_get_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- struct mfc_ctx_ctrl *ctx_ctrl;
- int found = 0;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
- ctrl->value = dec->loop_filter_mpeg4;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
- ctrl->value = dec->display_delay;
- break;
- case V4L2_CID_CACHEABLE:
- mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
- break;
- case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
- if (ctx->state >= MFCINST_HEAD_PARSED &&
- ctx->state < MFCINST_ABORT) {
- ctrl->value = ctx->dpb_count;
- break;
- } else if (ctx->state != MFCINST_INIT) {
- mfc_err_ctx("Decoding not initialised\n");
- return -EINVAL;
- }
-
- /* Should wait for the header to be parsed */
- if (mfc_wait_for_done_ctx(ctx,
- MFC_REG_R2H_CMD_SEQ_DONE_RET)) {
- mfc_cleanup_work_bit_and_try_run(ctx);
- return -EIO;
- }
-
- if (ctx->state >= MFCINST_HEAD_PARSED &&
- ctx->state < MFCINST_ABORT) {
- ctrl->value = ctx->dpb_count;
- } else {
- mfc_err_ctx("Decoding not initialised\n");
- return -EINVAL;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
- ctrl->value = dec->slice_enable;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
- /* Not used */
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
- ctrl->value = dec->crc_enable;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
- if (ctx->is_dpb_realloc && ctx->state == MFCINST_HEAD_PARSED)
- ctrl->value = MFCSTATE_DEC_S3D_REALLOC;
- else if (ctx->state == MFCINST_RES_CHANGE_FLUSH
- || ctx->state == MFCINST_RES_CHANGE_END
- || ctx->state == MFCINST_HEAD_PARSED)
- ctrl->value = MFCSTATE_DEC_RES_DETECT;
- else if (ctx->state == MFCINST_FINISHING)
- ctrl->value = MFCSTATE_DEC_TERMINATING;
- else
- ctrl->value = MFCSTATE_PROCESSING;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
- ctrl->value = dec->sei_parse;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
- ctrl->value = dec->idr_decoding;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE:
- ctrl->value = mfc_qos_get_framerate(ctx);
- break;
- case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
- ctrl->value = dev->pdata->ip_ver;
- break;
- case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
- ctrl->value = ctx->qos_ratio;
- break;
- case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
- ctrl->value = dec->is_dynamic_dpb;
- break;
- case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
- ctrl->value = __mfc_dec_ext_info(ctx);
- break;
- case V4L2_CID_MPEG_MFC_GET_10BIT_INFO:
- ctrl->value = ctx->is_10bit;
- break;
- case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
- ctrl->value = MFC_DRIVER_INFO;
- break;
- default:
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
-
- if (ctx_ctrl->id == ctrl->id) {
- if (ctx_ctrl->has_new) {
- ctx_ctrl->has_new = 0;
- ctrl->value = ctx_ctrl->val;
- } else {
- mfc_debug(5, "[CTRLS] Control value "\
- "is not up to date: "\
- "0x%08x\n", ctrl->id);
- return -EINVAL;
- }
-
- found = 1;
- break;
- }
- }
-
- if (!found) {
- mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
- return -EINVAL;
- }
- break;
- }
-
- mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
- return 0;
-}
-
-/* Get a ctrl */
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = 0;
-
- mfc_debug_enter();
- ret = __mfc_dec_get_ctrl_val(ctx, ctrl);
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Set a ctrl */
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct mfc_dev *dev = video_drvdata(file);
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec;
- struct mfc_ctx_ctrl *ctx_ctrl;
- int ret = 0;
- int found = 0;
-
- mfc_debug_enter();
-
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- ret = __mfc_dec_check_ctrl_val(ctx, ctrl);
- if (ret)
- return ret;
-
- mfc_debug(5, "[CTRLS] set id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
- dec->loop_filter_mpeg4 = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
- dec->display_delay = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
- dec->slice_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
- /* Not used */
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
- dec->crc_enable = ctrl->value;
- break;
- case V4L2_CID_CACHEABLE:
- mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
- dec->sei_parse = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
- dec->idr_decoding = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY:
- dec->immediate_display = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE:
- dec->is_dts_mode = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START:
- ctx->wait_state = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE:
- mfc_err_dev("[DPB] not supported CID: 0x%x\n",ctrl->id);
- break;
- case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
- ctx->qos_ratio = ctrl->value;
- mfc_info_ctx("[QoS] set %d qos_ratio\n", ctrl->value);
- break;
- case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
- dec->is_dynamic_dpb = ctrl->value;
- if (dec->is_dynamic_dpb == 0)
- mfc_err_dev("[DPB] is_dynamic_dpb is 0. it has to be enabled\n");
- break;
- case V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE:
- if (dec->sh_handle.fd == -1) {
- dec->sh_handle.fd = ctrl->value;
- if (mfc_mem_get_user_shared_handle(ctx, &dec->sh_handle))
- return -EINVAL;
- else
- mfc_debug(2, "[MEMINFO][DPB] shared handle fd: %d, vaddr: 0x%p\n",
- dec->sh_handle.fd, dec->sh_handle.vaddr);
- }
- break;
- case V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE:
- ctx->buf_process_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT:
- dec->detect_black_bar = ctrl->value;
- break;
- default:
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
- continue;
-
- if (ctx_ctrl->id == ctrl->id) {
- ctx_ctrl->has_new = 1;
- ctx_ctrl->val = ctrl->value;
-
- found = 1;
- break;
- }
- }
-
- if (!found) {
- mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
- return -EINVAL;
- }
- break;
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-/* Get cropping information */
-static int vidioc_g_crop(struct file *file, void *priv,
- struct v4l2_crop *cr)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_dec *dec = ctx->dec_priv;
-
- mfc_debug_enter();
-
- if (!ready_to_get_crop(ctx)) {
- mfc_debug(2, "ready to get crop failed\n");
- return -EINVAL;
- }
-
- if (ctx->state == MFCINST_RUNNING && dec->detect_black_bar
- && dec->black_bar_updated) {
- cr->c.left = dec->black_bar.left;
- cr->c.top = dec->black_bar.top;
- cr->c.width = dec->black_bar.width;
- cr->c.height = dec->black_bar.height;
- mfc_debug(2, "[FRAME][BLACKBAR] Cropping info: l=%d t=%d w=%d h=%d\n",
- dec->black_bar.left,
- dec->black_bar.top,
- dec->black_bar.width,
- dec->black_bar.height);
- } else {
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264 ||
- ctx->src_fmt->fourcc == V4L2_PIX_FMT_HEVC ||
- ctx->src_fmt->fourcc == V4L2_PIX_FMT_BPG) {
- cr->c.left = dec->cr_left;
- cr->c.top = dec->cr_top;
- cr->c.width = ctx->img_width - dec->cr_left - dec->cr_right;
- cr->c.height = ctx->img_height - dec->cr_top - dec->cr_bot;
- mfc_debug(2, "[FRAME] Cropping info: l=%d t=%d " \
- "w=%d h=%d (r=%d b=%d fw=%d fh=%d)\n",
- dec->cr_left, dec->cr_top,
- cr->c.width, cr->c.height,
- dec->cr_right, dec->cr_bot,
- ctx->img_width, ctx->img_height);
- } else {
- cr->c.left = 0;
- cr->c.top = 0;
- cr->c.width = ctx->img_width;
- cr->c.height = ctx->img_height;
- mfc_debug(2, "[FRAME] Cropping info: w=%d h=%d fw=%d fh=%d\n",
- cr->c.width, cr->c.height,
- ctx->img_width, ctx->img_height);
- }
- }
-
- mfc_debug_leave();
- return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct v4l2_ext_control *ext_ctrl;
- struct v4l2_control ctrl;
- int i;
- int ret = 0;
-
- if (f->which != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- for (i = 0; i < f->count; i++) {
- ext_ctrl = (f->controls + i);
-
- ctrl.id = ext_ctrl->id;
-
- ret = __mfc_dec_get_ctrl_val(ctx, &ctrl);
- if (ret == 0) {
- ext_ctrl->value = ctrl.value;
- } else {
- f->error_idx = i;
- break;
- }
-
- mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
- i, ext_ctrl->id, ext_ctrl->value);
- }
-
- return ret;
-}
-
-/* v4l2_ioctl_ops */
-static const struct v4l2_ioctl_ops mfc_dec_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
- .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
- .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap_mplane,
- .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out_mplane,
- .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
- .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
- .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane,
- .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out_mplane,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_crop = vidioc_g_crop,
- .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
-};
-
-const struct v4l2_ioctl_ops *mfc_get_dec_v4l2_ioctl_ops(void)
-{
- return &mfc_dec_ioctl_ops;
-}
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_dec.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MFC_DEC_H
-#define __MFC_DEC_H __FILE__
-
-#include "mfc_common.h"
-
-const struct v4l2_ioctl_ops *mfc_get_dec_v4l2_ioctl_ops(void);
-
-#endif /* __MFC_DEC_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_dec_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_common.h"
+
+#include "mfc_reg_api.h"
+
+#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
+
+struct mfc_ctrl_cfg mfc_ctrl_list[] = {
+ {
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_PICTURE_TAG,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_RET_PICTURE_TAG_TOP,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_STATUS,
+ .mask = 0x7,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ /* CRC related definitions are based on non-H.264 type */
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_FIRST_PLANE_CRC,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_SECOND_PLANE_CRC,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_THIRD_PLANE_CRC,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_FIRST_PLANE_2BIT_CRC,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_SECOND_PLANE_2BIT_CRC,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_DISPLAY_STATUS,
+ .mask = 0x1,
+ .shft = 6,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_SEI_AVAIL,
+ .mask = 0x1,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_FRAME_PACK_ARRGMENT_ID,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_FRAME_PACK_SEI_INFO,
+ .mask = 0x3FFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_FRAME_PACK_GRID_POS,
+ .mask = 0xFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MVC_VIEW_ID,
+ .mask = 0xFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
+ .mask = 0xFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
+ .mask = 0xFFFF,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_FORMAT,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
+ .mask = 0x7,
+ .shft = 26,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
+ .mask = 0x1,
+ .shft = 25,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
+ .mask = 0xFF,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ {
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+};
+
+static int mfc_dec_cleanup_ctx_ctrls(struct mfc_ctx *ctx)
+{
+ struct mfc_ctx_ctrl *ctx_ctrl;
+
+ while (!list_empty(&ctx->ctrls)) {
+ ctx_ctrl = list_entry((&ctx->ctrls)->next,
+ struct mfc_ctx_ctrl, list);
+ list_del(&ctx_ctrl->list);
+ kfree(ctx_ctrl);
+ }
+
+ INIT_LIST_HEAD(&ctx->ctrls);
+
+ return 0;
+}
+
+static int mfc_dec_init_ctx_ctrls(struct mfc_ctx *ctx)
+{
+ unsigned long i;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+
+ INIT_LIST_HEAD(&ctx->ctrls);
+
+ for (i = 0; i < NUM_CTRL_CFGS; i++) {
+ ctx_ctrl = kzalloc(sizeof(struct mfc_ctx_ctrl), GFP_KERNEL);
+ if (ctx_ctrl == NULL) {
+ mfc_err_dev("Failed to allocate context control "\
+ "id: 0x%08x, type: %d\n",
+ mfc_ctrl_list[i].id,
+ mfc_ctrl_list[i].type);
+
+ mfc_dec_cleanup_ctx_ctrls(ctx);
+
+ return -ENOMEM;
+ }
+
+ ctx_ctrl->type = mfc_ctrl_list[i].type;
+ ctx_ctrl->id = mfc_ctrl_list[i].id;
+ ctx_ctrl->addr = mfc_ctrl_list[i].addr;
+ ctx_ctrl->has_new = 0;
+ ctx_ctrl->val = 0;
+
+ list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
+ }
+
+ return 0;
+}
+
+static void __mfc_dec_remove_buf_ctrls(struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ while (!list_empty(head)) {
+ buf_ctrl = list_entry(head->next,
+ struct mfc_buf_ctrl, list);
+ list_del(&buf_ctrl->list);
+ kfree(buf_ctrl);
+ }
+
+ INIT_LIST_HEAD(head);
+}
+
+static void mfc_dec_reset_buf_ctrls(struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ buf_ctrl->has_new = 0;
+ buf_ctrl->val = 0;
+ buf_ctrl->old_val = 0;
+ buf_ctrl->updated = 0;
+ }
+}
+
+static int mfc_dec_init_buf_ctrls(struct mfc_ctx *ctx,
+ enum mfc_ctrl_type type, unsigned int index)
+{
+ unsigned long i;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct list_head *head;
+
+ if (index >= MFC_MAX_BUFFERS) {
+ mfc_err_dev("Per-buffer control index is out of range\n");
+ return -EINVAL;
+ }
+
+ if (type & MFC_CTRL_TYPE_SRC) {
+ if (test_bit(index, &ctx->src_ctrls_avail)) {
+ mfc_dec_reset_buf_ctrls(&ctx->src_ctrls[index]);
+
+ return 0;
+ }
+
+ head = &ctx->src_ctrls[index];
+ } else if (type & MFC_CTRL_TYPE_DST) {
+ if (test_bit(index, &ctx->dst_ctrls_avail)) {
+ mfc_dec_reset_buf_ctrls(&ctx->dst_ctrls[index]);
+
+ return 0;
+ }
+
+ head = &ctx->dst_ctrls[index];
+ } else {
+ mfc_err_dev("Control type mismatch. type : %d\n", type);
+ return -EINVAL;
+ }
+
+ INIT_LIST_HEAD(head);
+
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(type & ctx_ctrl->type))
+ continue;
+
+ /* find matched control configuration index */
+ for (i = 0; i < NUM_CTRL_CFGS; i++) {
+ if (ctx_ctrl->id == mfc_ctrl_list[i].id)
+ break;
+ }
+
+ if (i == NUM_CTRL_CFGS) {
+ mfc_err_dev("Failed to find buffer control "\
+ "id: 0x%08x, type: %d\n",
+ ctx_ctrl->id, ctx_ctrl->type);
+ continue;
+ }
+
+ buf_ctrl = kzalloc(sizeof(struct mfc_buf_ctrl), GFP_KERNEL);
+ if (buf_ctrl == NULL) {
+ mfc_err_dev("Failed to allocate buffer control "\
+ "id: 0x%08x, type: %d\n",
+ mfc_ctrl_list[i].id,
+ mfc_ctrl_list[i].type);
+
+ __mfc_dec_remove_buf_ctrls(head);
+
+ return -ENOMEM;
+ }
+
+ buf_ctrl->id = ctx_ctrl->id;
+ buf_ctrl->type = ctx_ctrl->type;
+ buf_ctrl->addr = ctx_ctrl->addr;
+
+ buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
+ buf_ctrl->mode = mfc_ctrl_list[i].mode;
+ buf_ctrl->mask = mfc_ctrl_list[i].mask;
+ buf_ctrl->shft = mfc_ctrl_list[i].shft;
+ buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
+ buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
+ buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
+
+ list_add_tail(&buf_ctrl->list, head);
+ }
+
+ mfc_dec_reset_buf_ctrls(head);
+
+ if (type & MFC_CTRL_TYPE_SRC)
+ set_bit(index, &ctx->src_ctrls_avail);
+ else
+ set_bit(index, &ctx->dst_ctrls_avail);
+
+ return 0;
+}
+
+static int mfc_dec_cleanup_buf_ctrls(struct mfc_ctx *ctx,
+ enum mfc_ctrl_type type, unsigned int index)
+{
+ struct list_head *head;
+
+ if (index >= MFC_MAX_BUFFERS) {
+ mfc_err_dev("Per-buffer control index is out of range\n");
+ return -EINVAL;
+ }
+
+ if (type & MFC_CTRL_TYPE_SRC) {
+ if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
+ return 0;
+ }
+
+ head = &ctx->src_ctrls[index];
+ } else if (type & MFC_CTRL_TYPE_DST) {
+ if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
+ return 0;
+ }
+
+ head = &ctx->dst_ctrls[index];
+ } else {
+ mfc_err_dev("Control type mismatch. type : %d\n", type);
+ return -EINVAL;
+ }
+
+ __mfc_dec_remove_buf_ctrls(head);
+
+ return 0;
+}
+
+static int mfc_dec_to_buf_ctrls(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
+ continue;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
+ continue;
+
+ if (buf_ctrl->id == ctx_ctrl->id) {
+ buf_ctrl->has_new = 1;
+ buf_ctrl->val = ctx_ctrl->val;
+ if (buf_ctrl->is_volatile)
+ buf_ctrl->updated = 0;
+
+ ctx_ctrl->has_new = 0;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mfc_dec_to_ctx_ctrls(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
+ continue;
+
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+
+ if (ctx_ctrl->id == buf_ctrl->id) {
+ ctx_ctrl->has_new = 1;
+ ctx_ctrl->val = buf_ctrl->val;
+
+ buf_ctrl->has_new = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mfc_dec_set_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_dev *dev = ctx->dev;
+ unsigned int value = 0;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+ continue;
+
+ /* read old vlaue */
+ value = MFC_READL(buf_ctrl->addr);
+
+ /* save old vlaue for recovery */
+ if (buf_ctrl->is_volatile)
+ buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+ /* write new value */
+ value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
+ MFC_WRITEL(value, buf_ctrl->addr);
+
+ /* set change flag bit */
+ if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value |= (1 << buf_ctrl->flag_shft);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ }
+
+ buf_ctrl->has_new = 0;
+ buf_ctrl->updated = 1;
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
+ dec->stored_tag = buf_ctrl->val;
+
+ mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ return 0;
+}
+
+static int mfc_dec_get_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ unsigned int value = 0;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+
+ value = MFC_READL(buf_ctrl->addr);
+ value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+ buf_ctrl->val = value;
+ buf_ctrl->has_new = 1;
+
+ if (IS_VP9_DEC(ctx)) {
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
+ buf_ctrl->val = dec->color_range;
+ else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
+ buf_ctrl->val = dec->color_space;
+ }
+
+ mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ return 0;
+}
+
+static int mfc_dec_set_buf_ctrls_val_nal_q_dec(struct mfc_ctx *ctx,
+ struct list_head *head, DecoderInputStr *pInStr)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dec *dec = ctx->dec_priv;
+
+ mfc_debug_enter();
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+ continue;
+ switch (buf_ctrl->id) {
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+ pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->PictureTag |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ dec->stored_tag = buf_ctrl->val;
+ break;
+ /* If new dynamic controls are added, insert here */
+ default:
+ mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+ buf_ctrl->id);
+ }
+ buf_ctrl->has_new = 0;
+ buf_ctrl->updated = 1;
+
+ mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int mfc_dec_get_buf_ctrls_val_nal_q_dec(struct mfc_ctx *ctx,
+ struct list_head *head, DecoderOutputStr *pOutStr)
+{
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_buf_ctrl *buf_ctrl;
+ unsigned int value = 0;
+
+ mfc_debug_enter();
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+ switch (buf_ctrl->id) {
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+ value = pOutStr->PictureTagTop;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS:
+ value = pOutStr->DisplayStatus;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA:
+ value = pOutStr->DisplayFirstCrc;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA:
+ value = pOutStr->DisplaySecondCrc;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1:
+ value = pOutStr->DisplayThirdCrc;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA:
+ value = pOutStr->DisplayFirst2BitCrc;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA:
+ value = pOutStr->DisplaySecond2BitCrc;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED:
+ value = pOutStr->DisplayStatus;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL:
+ value = pOutStr->SeiAvail;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID:
+ value = pOutStr->FramePackArrgmentId;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO:
+ value = pOutStr->FramePackSeiInfo;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS:
+ value = pOutStr->FramePackGridPos;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID:
+ value = 0;
+ break;
+ /* TO-DO: SEI information has to be added in NAL-Q */
+ case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
+ case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
+ value = pOutStr->ContentLightLevelInfoSei;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
+ value = pOutStr->MasteringDisplayColourVolumeSei0;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
+ value = pOutStr->MasteringDisplayColourVolumeSei1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
+ case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
+ case V4L2_CID_MPEG_VIDEO_FORMAT:
+ case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
+ case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
+ value = pOutStr->VideoSignalType;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
+ value = pOutStr->MasteringDisplayColourVolumeSei2;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
+ value = pOutStr->MasteringDisplayColourVolumeSei3;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
+ value = pOutStr->MasteringDisplayColourVolumeSei4;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
+ value = pOutStr->MasteringDisplayColourVolumeSei5;
+ break;
+ /* If new dynamic controls are added, insert here */
+ default:
+ mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+ buf_ctrl->id);
+ }
+ value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+ buf_ctrl->val = value;
+ buf_ctrl->has_new = 1;
+
+ if (IS_VP9_DEC(ctx)) {
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
+ buf_ctrl->val = dec->color_range;
+ else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
+ buf_ctrl->val = dec->color_space;
+ }
+
+ mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int mfc_dec_recover_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dev *dev = ctx->dev;
+ unsigned int value = 0;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+ || !buf_ctrl->is_volatile
+ || !buf_ctrl->updated)
+ continue;
+
+ value = MFC_READL(buf_ctrl->addr);
+ value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ value |= ((buf_ctrl->old_val & buf_ctrl->mask) << buf_ctrl->shft);
+ MFC_WRITEL(value, buf_ctrl->addr);
+
+ /* clear change flag bit */
+ if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value &= ~(1 << buf_ctrl->flag_shft);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ }
+
+ buf_ctrl->updated = 0;
+ mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
+ buf_ctrl->id, buf_ctrl->old_val);
+ }
+
+ return 0;
+}
+
+static int mfc_dec_get_buf_update_val(struct mfc_ctx *ctx,
+ struct list_head *head, unsigned int id, int value)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (buf_ctrl->id == id) {
+ buf_ctrl->val = value;
+ mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int mfc_dec_recover_buf_ctrls_nal_q(struct mfc_ctx *ctx,
+ struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+ || !(buf_ctrl->updated))
+ continue;
+
+ buf_ctrl->has_new = 1;
+ buf_ctrl->updated = 0;
+ mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ return 0;
+}
+
+struct mfc_ctrls_ops decoder_ctrls_ops = {
+ .init_ctx_ctrls = mfc_dec_init_ctx_ctrls,
+ .cleanup_ctx_ctrls = mfc_dec_cleanup_ctx_ctrls,
+ .init_buf_ctrls = mfc_dec_init_buf_ctrls,
+ .reset_buf_ctrls = mfc_dec_reset_buf_ctrls,
+ .cleanup_buf_ctrls = mfc_dec_cleanup_buf_ctrls,
+ .to_buf_ctrls = mfc_dec_to_buf_ctrls,
+ .to_ctx_ctrls = mfc_dec_to_ctx_ctrls,
+ .set_buf_ctrls_val = mfc_dec_set_buf_ctrls_val,
+ .get_buf_ctrls_val = mfc_dec_get_buf_ctrls_val,
+ .set_buf_ctrls_val_nal_q_dec = mfc_dec_set_buf_ctrls_val_nal_q_dec,
+ .get_buf_ctrls_val_nal_q_dec = mfc_dec_get_buf_ctrls_val_nal_q_dec,
+ .recover_buf_ctrls_val = mfc_dec_recover_buf_ctrls_val,
+ .get_buf_update_val = mfc_dec_get_buf_update_val,
+ .recover_buf_ctrls_nal_q = mfc_dec_recover_buf_ctrls_nal_q,
+};
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_dec_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_common.h"
-
-#include "mfc_reg.h"
-
-#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
-
-struct mfc_ctrl_cfg mfc_ctrl_list[] = {
- {
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_PICTURE_TAG,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_RET_PICTURE_TAG_TOP,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_STATUS,
- .mask = 0x7,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- /* CRC related definitions are based on non-H.264 type */
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_FIRST_PLANE_CRC,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_SECOND_PLANE_CRC,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_THIRD_PLANE_CRC,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_FIRST_PLANE_2BIT_CRC,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_SECOND_PLANE_2BIT_CRC,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_DISPLAY_STATUS,
- .mask = 0x1,
- .shft = 6,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_SEI_AVAIL,
- .mask = 0x1,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_FRAME_PACK_ARRGMENT_ID,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_FRAME_PACK_SEI_INFO,
- .mask = 0x3FFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_FRAME_PACK_GRID_POS,
- .mask = 0xFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MVC_VIEW_ID,
- .mask = 0xFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
- .mask = 0xFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
- .mask = 0xFFFF,
- .shft = 16,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_FORMAT,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
- .mask = 0x7,
- .shft = 26,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
- .mask = 0x1,
- .shft = 25,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
- .mask = 0xFF,
- .shft = 16,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_VIDEO_SIGNAL_TYPE,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- {
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
-};
-
-static int mfc_dec_cleanup_ctx_ctrls(struct mfc_ctx *ctx)
-{
- struct mfc_ctx_ctrl *ctx_ctrl;
-
- while (!list_empty(&ctx->ctrls)) {
- ctx_ctrl = list_entry((&ctx->ctrls)->next,
- struct mfc_ctx_ctrl, list);
- list_del(&ctx_ctrl->list);
- kfree(ctx_ctrl);
- }
-
- INIT_LIST_HEAD(&ctx->ctrls);
-
- return 0;
-}
-
-static int mfc_dec_init_ctx_ctrls(struct mfc_ctx *ctx)
-{
- unsigned long i;
- struct mfc_ctx_ctrl *ctx_ctrl;
-
- INIT_LIST_HEAD(&ctx->ctrls);
-
- for (i = 0; i < NUM_CTRL_CFGS; i++) {
- ctx_ctrl = kzalloc(sizeof(struct mfc_ctx_ctrl), GFP_KERNEL);
- if (ctx_ctrl == NULL) {
- mfc_err_dev("Failed to allocate context control "\
- "id: 0x%08x, type: %d\n",
- mfc_ctrl_list[i].id,
- mfc_ctrl_list[i].type);
-
- mfc_dec_cleanup_ctx_ctrls(ctx);
-
- return -ENOMEM;
- }
-
- ctx_ctrl->type = mfc_ctrl_list[i].type;
- ctx_ctrl->id = mfc_ctrl_list[i].id;
- ctx_ctrl->addr = mfc_ctrl_list[i].addr;
- ctx_ctrl->has_new = 0;
- ctx_ctrl->val = 0;
-
- list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
- }
-
- return 0;
-}
-
-static void __mfc_dec_remove_buf_ctrls(struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- while (!list_empty(head)) {
- buf_ctrl = list_entry(head->next,
- struct mfc_buf_ctrl, list);
- list_del(&buf_ctrl->list);
- kfree(buf_ctrl);
- }
-
- INIT_LIST_HEAD(head);
-}
-
-static void mfc_dec_reset_buf_ctrls(struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- buf_ctrl->has_new = 0;
- buf_ctrl->val = 0;
- buf_ctrl->old_val = 0;
- buf_ctrl->updated = 0;
- }
-}
-
-static int mfc_dec_init_buf_ctrls(struct mfc_ctx *ctx,
- enum mfc_ctrl_type type, unsigned int index)
-{
- unsigned long i;
- struct mfc_ctx_ctrl *ctx_ctrl;
- struct mfc_buf_ctrl *buf_ctrl;
- struct list_head *head;
-
- if (index >= MFC_MAX_BUFFERS) {
- mfc_err_dev("Per-buffer control index is out of range\n");
- return -EINVAL;
- }
-
- if (type & MFC_CTRL_TYPE_SRC) {
- if (test_bit(index, &ctx->src_ctrls_avail)) {
- mfc_dec_reset_buf_ctrls(&ctx->src_ctrls[index]);
-
- return 0;
- }
-
- head = &ctx->src_ctrls[index];
- } else if (type & MFC_CTRL_TYPE_DST) {
- if (test_bit(index, &ctx->dst_ctrls_avail)) {
- mfc_dec_reset_buf_ctrls(&ctx->dst_ctrls[index]);
-
- return 0;
- }
-
- head = &ctx->dst_ctrls[index];
- } else {
- mfc_err_dev("Control type mismatch. type : %d\n", type);
- return -EINVAL;
- }
-
- INIT_LIST_HEAD(head);
-
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(type & ctx_ctrl->type))
- continue;
-
- /* find matched control configuration index */
- for (i = 0; i < NUM_CTRL_CFGS; i++) {
- if (ctx_ctrl->id == mfc_ctrl_list[i].id)
- break;
- }
-
- if (i == NUM_CTRL_CFGS) {
- mfc_err_dev("Failed to find buffer control "\
- "id: 0x%08x, type: %d\n",
- ctx_ctrl->id, ctx_ctrl->type);
- continue;
- }
-
- buf_ctrl = kzalloc(sizeof(struct mfc_buf_ctrl), GFP_KERNEL);
- if (buf_ctrl == NULL) {
- mfc_err_dev("Failed to allocate buffer control "\
- "id: 0x%08x, type: %d\n",
- mfc_ctrl_list[i].id,
- mfc_ctrl_list[i].type);
-
- __mfc_dec_remove_buf_ctrls(head);
-
- return -ENOMEM;
- }
-
- buf_ctrl->id = ctx_ctrl->id;
- buf_ctrl->type = ctx_ctrl->type;
- buf_ctrl->addr = ctx_ctrl->addr;
-
- buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
- buf_ctrl->mode = mfc_ctrl_list[i].mode;
- buf_ctrl->mask = mfc_ctrl_list[i].mask;
- buf_ctrl->shft = mfc_ctrl_list[i].shft;
- buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
- buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
- buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
-
- list_add_tail(&buf_ctrl->list, head);
- }
-
- mfc_dec_reset_buf_ctrls(head);
-
- if (type & MFC_CTRL_TYPE_SRC)
- set_bit(index, &ctx->src_ctrls_avail);
- else
- set_bit(index, &ctx->dst_ctrls_avail);
-
- return 0;
-}
-
-static int mfc_dec_cleanup_buf_ctrls(struct mfc_ctx *ctx,
- enum mfc_ctrl_type type, unsigned int index)
-{
- struct list_head *head;
-
- if (index >= MFC_MAX_BUFFERS) {
- mfc_err_dev("Per-buffer control index is out of range\n");
- return -EINVAL;
- }
-
- if (type & MFC_CTRL_TYPE_SRC) {
- if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
- return 0;
- }
-
- head = &ctx->src_ctrls[index];
- } else if (type & MFC_CTRL_TYPE_DST) {
- if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
- return 0;
- }
-
- head = &ctx->dst_ctrls[index];
- } else {
- mfc_err_dev("Control type mismatch. type : %d\n", type);
- return -EINVAL;
- }
-
- __mfc_dec_remove_buf_ctrls(head);
-
- return 0;
-}
-
-static int mfc_dec_to_buf_ctrls(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_ctx_ctrl *ctx_ctrl;
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
- continue;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
- continue;
-
- if (buf_ctrl->id == ctx_ctrl->id) {
- buf_ctrl->has_new = 1;
- buf_ctrl->val = ctx_ctrl->val;
- if (buf_ctrl->is_volatile)
- buf_ctrl->updated = 0;
-
- ctx_ctrl->has_new = 0;
- break;
- }
- }
- }
-
- return 0;
-}
-
-static int mfc_dec_to_ctx_ctrls(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_ctx_ctrl *ctx_ctrl;
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
- continue;
-
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
-
- if (ctx_ctrl->id == buf_ctrl->id) {
- ctx_ctrl->has_new = 1;
- ctx_ctrl->val = buf_ctrl->val;
-
- buf_ctrl->has_new = 0;
- }
- }
- }
-
- return 0;
-}
-
-static int mfc_dec_set_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_dev *dev = ctx->dev;
- unsigned int value = 0;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
- continue;
-
- /* read old vlaue */
- value = MFC_READL(buf_ctrl->addr);
-
- /* save old vlaue for recovery */
- if (buf_ctrl->is_volatile)
- buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
- /* write new value */
- value &= ~(buf_ctrl->mask << buf_ctrl->shft);
- value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
- MFC_WRITEL(value, buf_ctrl->addr);
-
- /* set change flag bit */
- if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
- value = MFC_READL(buf_ctrl->flag_addr);
- value |= (1 << buf_ctrl->flag_shft);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- }
-
- buf_ctrl->has_new = 0;
- buf_ctrl->updated = 1;
-
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
- dec->stored_tag = buf_ctrl->val;
-
- mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- return 0;
-}
-
-static int mfc_dec_get_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- unsigned int value = 0;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
-
- value = MFC_READL(buf_ctrl->addr);
- value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
- buf_ctrl->val = value;
- buf_ctrl->has_new = 1;
-
- if (IS_VP9_DEC(ctx)) {
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
- buf_ctrl->val = dec->color_range;
- else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
- buf_ctrl->val = dec->color_space;
- }
-
- mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- return 0;
-}
-
-static int mfc_dec_set_buf_ctrls_val_nal_q_dec(struct mfc_ctx *ctx,
- struct list_head *head, DecoderInputStr *pInStr)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dec *dec = ctx->dec_priv;
-
- mfc_debug_enter();
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
- continue;
- switch (buf_ctrl->id) {
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
- pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->PictureTag |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- dec->stored_tag = buf_ctrl->val;
- break;
- /* If new dynamic controls are added, insert here */
- default:
- mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
- buf_ctrl->id);
- }
- buf_ctrl->has_new = 0;
- buf_ctrl->updated = 1;
-
- mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int mfc_dec_get_buf_ctrls_val_nal_q_dec(struct mfc_ctx *ctx,
- struct list_head *head, DecoderOutputStr *pOutStr)
-{
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_buf_ctrl *buf_ctrl;
- unsigned int value = 0;
-
- mfc_debug_enter();
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
- switch (buf_ctrl->id) {
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
- value = pOutStr->PictureTagTop;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS:
- value = pOutStr->DisplayStatus;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA:
- value = pOutStr->DisplayFirstCrc;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA:
- value = pOutStr->DisplaySecondCrc;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1:
- value = pOutStr->DisplayThirdCrc;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA:
- value = pOutStr->DisplayFirst2BitCrc;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA:
- value = pOutStr->DisplaySecond2BitCrc;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED:
- value = pOutStr->DisplayStatus;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL:
- value = pOutStr->SeiAvail;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID:
- value = pOutStr->FramePackArrgmentId;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO:
- value = pOutStr->FramePackSeiInfo;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS:
- value = pOutStr->FramePackGridPos;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID:
- value = 0;
- break;
- /* TO-DO: SEI information has to be added in NAL-Q */
- case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
- case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
- value = pOutStr->ContentLightLevelInfoSei;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
- value = pOutStr->MasteringDisplayColourVolumeSei0;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
- value = pOutStr->MasteringDisplayColourVolumeSei1;
- break;
- case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
- case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
- case V4L2_CID_MPEG_VIDEO_FORMAT:
- case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
- case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
- value = pOutStr->VideoSignalType;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
- value = pOutStr->MasteringDisplayColourVolumeSei2;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
- value = pOutStr->MasteringDisplayColourVolumeSei3;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
- value = pOutStr->MasteringDisplayColourVolumeSei4;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
- value = pOutStr->MasteringDisplayColourVolumeSei5;
- break;
- /* If new dynamic controls are added, insert here */
- default:
- mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
- buf_ctrl->id);
- }
- value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
- buf_ctrl->val = value;
- buf_ctrl->has_new = 1;
-
- if (IS_VP9_DEC(ctx)) {
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
- buf_ctrl->val = dec->color_range;
- else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
- buf_ctrl->val = dec->color_space;
- }
-
- mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int mfc_dec_recover_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dev *dev = ctx->dev;
- unsigned int value = 0;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
- || !buf_ctrl->is_volatile
- || !buf_ctrl->updated)
- continue;
-
- value = MFC_READL(buf_ctrl->addr);
- value &= ~(buf_ctrl->mask << buf_ctrl->shft);
- value |= ((buf_ctrl->old_val & buf_ctrl->mask) << buf_ctrl->shft);
- MFC_WRITEL(value, buf_ctrl->addr);
-
- /* clear change flag bit */
- if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
- value = MFC_READL(buf_ctrl->flag_addr);
- value &= ~(1 << buf_ctrl->flag_shft);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- }
-
- buf_ctrl->updated = 0;
- mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
- buf_ctrl->id, buf_ctrl->old_val);
- }
-
- return 0;
-}
-
-static int mfc_dec_get_buf_update_val(struct mfc_ctx *ctx,
- struct list_head *head, unsigned int id, int value)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (buf_ctrl->id == id) {
- buf_ctrl->val = value;
- mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- break;
- }
- }
-
- return 0;
-}
-
-static int mfc_dec_recover_buf_ctrls_nal_q(struct mfc_ctx *ctx,
- struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
- || !(buf_ctrl->updated))
- continue;
-
- buf_ctrl->has_new = 1;
- buf_ctrl->updated = 0;
- mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- return 0;
-}
-
-struct mfc_ctrls_ops decoder_ctrls_ops = {
- .init_ctx_ctrls = mfc_dec_init_ctx_ctrls,
- .cleanup_ctx_ctrls = mfc_dec_cleanup_ctx_ctrls,
- .init_buf_ctrls = mfc_dec_init_buf_ctrls,
- .reset_buf_ctrls = mfc_dec_reset_buf_ctrls,
- .cleanup_buf_ctrls = mfc_dec_cleanup_buf_ctrls,
- .to_buf_ctrls = mfc_dec_to_buf_ctrls,
- .to_ctx_ctrls = mfc_dec_to_ctx_ctrls,
- .set_buf_ctrls_val = mfc_dec_set_buf_ctrls_val,
- .get_buf_ctrls_val = mfc_dec_get_buf_ctrls_val,
- .set_buf_ctrls_val_nal_q_dec = mfc_dec_set_buf_ctrls_val_nal_q_dec,
- .get_buf_ctrls_val_nal_q_dec = mfc_dec_get_buf_ctrls_val_nal_q_dec,
- .recover_buf_ctrls_val = mfc_dec_recover_buf_ctrls_val,
- .get_buf_update_val = mfc_dec_get_buf_update_val,
- .recover_buf_ctrls_nal_q = mfc_dec_recover_buf_ctrls_nal_q,
-};
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_dec_v4l2.h"
+#include "mfc_dec_internal.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+#include "mfc_mmcache.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+#define MAX_FRAME_SIZE (2*1024*1024)
+
+/* Find selected format description */
+static struct mfc_fmt *__mfc_dec_find_format(struct mfc_ctx *ctx,
+ unsigned int pixelformat)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_fmt *fmt = NULL;
+ unsigned long i;
+
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (dec_formats[i].fourcc == pixelformat) {
+ fmt = (struct mfc_fmt *)&dec_formats[i];
+ break;
+ }
+ }
+
+ if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
+ mfc_err_ctx("[FRAME] 10bit is not supported\n");
+ fmt = NULL;
+ }
+ if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
+ mfc_err_ctx("[FRAME] 422 is not supported\n");
+ fmt = NULL;
+ }
+
+ return fmt;
+}
+
+static struct v4l2_queryctrl *__mfc_dec_get_ctrl(int id)
+{
+ unsigned long i;
+
+ for (i = 0; i < NUM_CTRLS; ++i)
+ if (id == controls[i].id)
+ return &controls[i];
+
+ return NULL;
+}
+
+/* Check whether a ctrl value if correct */
+static int __mfc_dec_check_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct v4l2_queryctrl *c;
+
+ c = __mfc_dec_get_ctrl(ctrl->id);
+ if (!c) {
+ mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
+ return -EINVAL;
+ }
+
+ if (ctrl->value < c->minimum || ctrl->value > c->maximum
+ || (c->step != 0 && ctrl->value % c->step != 0)) {
+ mfc_err_ctx("[CTRLS] Invalid control value (%#x)\n", ctrl->value);
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
+ strncpy(cap->card, "decoder", sizeof(cap->card) - 1);
+ cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+ | V4L2_CAP_VIDEO_OUTPUT
+ | V4L2_CAP_VIDEO_CAPTURE_MPLANE
+ | V4L2_CAP_VIDEO_OUTPUT_MPLANE
+ | V4L2_CAP_STREAMING
+ | V4L2_CAP_DEVICE_CAPS;
+
+ cap->capabilities = cap->device_caps;
+
+ return 0;
+}
+
+static int __mfc_dec_enum_fmt(struct mfc_dev *dev, struct v4l2_fmtdesc *f,
+ unsigned int type)
+{
+ struct mfc_fmt *fmt;
+ unsigned long i, j = 0;
+
+ for (i = 0; i < NUM_FORMATS; ++i) {
+ if (!(dec_formats[i].type & type))
+ continue;
+ if (!dev->pdata->support_10bit && (dec_formats[i].type & MFC_FMT_10BIT))
+ continue;
+ if (!dev->pdata->support_422 && (dec_formats[i].type & MFC_FMT_422))
+ continue;
+
+ if (j == f->index) {
+ fmt = &dec_formats[i];
+ strlcpy(f->description, fmt->name,
+ sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
+
+ return 0;
+ }
+
+ ++j;
+ }
+
+ return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+ struct v4l2_fmtdesc *f)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+
+ return __mfc_dec_enum_fmt(dev, f, MFC_FMT_FRAME);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+ struct v4l2_fmtdesc *f)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+
+ return __mfc_dec_enum_fmt(dev, f, MFC_FMT_STREAM);
+}
+
+static void __mfc_dec_change_format(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ u32 org_fmt = ctx->dst_fmt->fourcc;
+
+ if (ctx->is_10bit && ctx->is_422) {
+ switch (org_fmt) {
+ case V4L2_PIX_FMT_NV16M_S10B:
+ case V4L2_PIX_FMT_NV61M_S10B:
+ case V4L2_PIX_FMT_NV16M_P210:
+ case V4L2_PIX_FMT_NV61M_P210:
+ /* It is right format */
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV12M_S10B:
+ case V4L2_PIX_FMT_NV12M_P010:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
+ break;
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV61M:
+ case V4L2_PIX_FMT_NV21M_S10B:
+ case V4L2_PIX_FMT_NV21M_P010:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M_S10B);
+ break;
+ default:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
+ break;
+ }
+ ctx->raw_buf.num_planes = 2;
+ } else if (ctx->is_10bit && !ctx->is_422) {
+ if (ctx->dst_fmt->mem_planes == 1) {
+ /* YUV420 only supports the single plane */
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12N_10B);
+ } else {
+ switch (org_fmt) {
+ case V4L2_PIX_FMT_NV12M_S10B:
+ case V4L2_PIX_FMT_NV21M_S10B:
+ case V4L2_PIX_FMT_NV12M_P010:
+ case V4L2_PIX_FMT_NV21M_P010:
+ /* It is right format */
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV16M_S10B:
+ case V4L2_PIX_FMT_NV16M_P210:
+ if (dev->pdata->P010_decoding)
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
+ else
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
+ break;
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV61M:
+ case V4L2_PIX_FMT_NV61M_S10B:
+ case V4L2_PIX_FMT_NV61M_P210:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M_S10B);
+ break;
+ default:
+ if (dev->pdata->P010_decoding)
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
+ else
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
+ break;
+ }
+ }
+ ctx->raw_buf.num_planes = 2;
+ } else if (!ctx->is_10bit && ctx->is_422) {
+ switch (org_fmt) {
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV61M:
+ /* It is right format */
+ break;
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12M_S10B:
+ case V4L2_PIX_FMT_NV16M_S10B:
+ case V4L2_PIX_FMT_NV12M_P010:
+ case V4L2_PIX_FMT_NV16M_P210:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
+ break;
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV21M_S10B:
+ case V4L2_PIX_FMT_NV61M_S10B:
+ case V4L2_PIX_FMT_NV21M_P010:
+ case V4L2_PIX_FMT_NV61M_P210:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M);
+ break;
+ default:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
+ break;
+ }
+ ctx->raw_buf.num_planes = 2;
+ } else {
+ /* YUV420 8bit */
+ switch (org_fmt) {
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV12M_S10B:
+ case V4L2_PIX_FMT_NV16M_S10B:
+ case V4L2_PIX_FMT_NV12M_P010:
+ case V4L2_PIX_FMT_NV16M_P210:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M);
+ break;
+ case V4L2_PIX_FMT_NV61M:
+ case V4L2_PIX_FMT_NV21M_S10B:
+ case V4L2_PIX_FMT_NV61M_S10B:
+ case V4L2_PIX_FMT_NV21M_P010:
+ case V4L2_PIX_FMT_NV61M_P210:
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M);
+ break;
+ default:
+ /* It is right format */
+ break;
+ }
+ }
+
+ if (org_fmt != ctx->dst_fmt->fourcc)
+ mfc_info_ctx("[FRAME] format is changed to %s\n", ctx->dst_fmt->name);
+}
+
+/* Get format */
+static int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+ struct mfc_raw_info *raw;
+ int i;
+
+ mfc_debug_enter();
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ mfc_debug(2, "dec dst g_fmt, state: %d\n", ctx->state);
+
+ if (ctx->state == MFCINST_GOT_INST ||
+ ctx->state == MFCINST_RES_CHANGE_FLUSH ||
+ ctx->state == MFCINST_RES_CHANGE_END) {
+ /* If the MFC is parsing the header,
+ * so wait until it is finished */
+ if (mfc_wait_for_done_ctx(ctx,
+ MFC_REG_R2H_CMD_SEQ_DONE_RET)) {
+ mfc_err_dev("header parsing failed\n");
+ return -EAGAIN;
+ }
+ }
+
+ if (ctx->state >= MFCINST_HEAD_PARSED &&
+ ctx->state < MFCINST_ABORT) {
+ /* This is run on CAPTURE (deocde output) */
+
+ /* only NV16(61) format is supported for 422 format */
+ /* only 2 plane is supported for 10bit */
+ __mfc_dec_change_format(ctx);
+
+ raw = &ctx->raw_buf;
+ /* Width and height are set to the dimensions
+ of the movie, the buffer is bigger and
+ further processing stages should crop to this
+ rectangle. */
+ mfc_dec_calc_dpb_size(ctx);
+
+ if (IS_LOW_MEM) {
+ unsigned int dpb_size;
+ /*
+ * If total memory requirement is too big for this device,
+ * then it returns error.
+ * DPB size : Total plane size * the number of DPBs
+ * 5: the number of extra DPBs
+ * 3: the number of DPBs for Android framework
+ * 600MB: being used to return an error,
+ * when 8K resolution video clip is being tried to be decoded
+ */
+ dpb_size = (ctx->raw_buf.total_plane_size * (ctx->dpb_count + 5 + 3));
+ if (dpb_size > SZ_600M) {
+ mfc_info_ctx("required memory size is too big (%dx%d, dpb: %d)\n",
+ ctx->img_width, ctx->img_height, ctx->dpb_count);
+ return -EINVAL;
+ }
+ }
+
+ pix_fmt_mp->width = ctx->img_width;
+ pix_fmt_mp->height = ctx->img_height;
+ pix_fmt_mp->num_planes = ctx->dst_fmt->mem_planes;
+
+ if (dec->is_interlaced)
+ pix_fmt_mp->field = V4L2_FIELD_INTERLACED;
+ else
+ pix_fmt_mp->field = V4L2_FIELD_NONE;
+
+ /* Set pixelformat to the format in which MFC
+ outputs the decoded frame */
+ pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
+ for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
+ pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
+ if (ctx->dst_fmt->mem_planes == 1) {
+ pix_fmt_mp->plane_fmt[i].sizeimage = raw->total_plane_size;
+ } else {
+ if (ctx->is_10bit)
+ pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i]
+ + raw->plane_size_2bits[i];
+ else
+ pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
+ }
+ }
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+ mfc_debug_enter();
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ mfc_debug(4, "dec src g_fmt, state: %d\n", ctx->state);
+
+ /* This is run on OUTPUT
+ The buffer contains compressed image
+ so width and height have no meaning */
+ pix_fmt_mp->width = 0;
+ pix_fmt_mp->height = 0;
+ pix_fmt_mp->field = V4L2_FIELD_NONE;
+ pix_fmt_mp->plane_fmt[0].bytesperline = dec->src_buf_size;
+ pix_fmt_mp->plane_fmt[0].sizeimage = dec->src_buf_size;
+ pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
+ pix_fmt_mp->num_planes = ctx->src_fmt->mem_planes;
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Try format */
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_fmt *fmt;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+ fmt = __mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
+ if (!fmt) {
+ mfc_err_dev("Unsupported format for %s\n",
+ V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Set format */
+static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+ mfc_debug_enter();
+
+ if (ctx->vq_dst.streaming) {
+ mfc_err_ctx("queue busy\n");
+ return -EBUSY;
+ }
+
+ ctx->dst_fmt = __mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
+ if (!ctx->dst_fmt) {
+ mfc_err_ctx("Unsupported format for destination\n");
+ return -EINVAL;
+ }
+ ctx->raw_buf.num_planes = ctx->dst_fmt->num_planes;
+ mfc_info_ctx("[FRAME] dec dst pixelformat : %s\n", ctx->dst_fmt->name);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int __mfc_force_close_inst(struct mfc_dev *dev, struct mfc_ctx *ctx)
+{
+ if (ctx->inst_no == MFC_NO_INSTANCE_SET)
+ return 0;
+
+ mfc_change_state(ctx, MFCINST_RETURN_INST);
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ mfc_clean_ctx_int_flags(ctx);
+ if (mfc_just_run(dev, ctx->num)) {
+ mfc_err_ctx("Failed to run MFC\n");
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ return -EIO;
+ }
+
+ /* Wait until instance is returned or timeout occured */
+ if (mfc_wait_for_done_ctx(ctx,
+ MFC_REG_R2H_CMD_CLOSE_INSTANCE_RET)) {
+ mfc_err_ctx("Waiting for CLOSE_INSTANCE timed out\n");
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ return -EIO;
+ }
+
+ /* Free resources */
+ mfc_release_instance_context(ctx);
+ mfc_change_state(ctx, MFCINST_INIT);
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+ int ret = 0;
+
+ mfc_debug_enter();
+
+ if (ctx->vq_src.streaming) {
+ mfc_err_ctx("queue busy\n");
+ return -EBUSY;
+ }
+
+ ctx->src_fmt = __mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
+ if (!ctx->src_fmt) {
+ mfc_err_ctx("Unsupported format for source\n");
+ return -EINVAL;
+ }
+
+ ctx->codec_mode = ctx->src_fmt->codec_mode;
+ mfc_info_ctx("[STREAM] Dec src codec(%d): %s\n",
+ ctx->codec_mode, ctx->src_fmt->name);
+
+ ctx->pix_format = pix_fmt_mp->pixelformat;
+ if ((pix_fmt_mp->width > 0) && (pix_fmt_mp->height > 0)) {
+ ctx->img_height = pix_fmt_mp->height;
+ ctx->img_width = pix_fmt_mp->width;
+ }
+
+ /* As this buffer will contain compressed data, the size is set
+ * to the maximum size. */
+ if (pix_fmt_mp->plane_fmt[0].sizeimage)
+ dec->src_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
+ else
+ dec->src_buf_size = MAX_FRAME_SIZE;
+ mfc_debug(2, "[STREAM] sizeimage: %d\n", pix_fmt_mp->plane_fmt[0].sizeimage);
+ pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+
+ MFC_TRACE_CTX_HWLOCK("**DEC s_fmt\n");
+ ret = mfc_get_hwlock_ctx(ctx);
+ if (ret < 0) {
+ mfc_err_ctx("Failed to get hwlock\n");
+ return -EBUSY;
+ }
+
+ /* In case of calling s_fmt twice or more */
+ ret = __mfc_force_close_inst(dev, ctx);
+ if (ret) {
+ mfc_err_ctx("Failed to close already opening instance\n");
+ return -EIO;
+ }
+
+ ret = mfc_alloc_instance_context(ctx);
+ if (ret) {
+ mfc_err_ctx("Failed to allocate dec instance[%d] buffers\n",
+ ctx->num);
+ mfc_release_hwlock_ctx(ctx);
+ return -ENOMEM;
+ }
+
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ ret = mfc_just_run(dev, ctx->num);
+ if (ret) {
+ mfc_err_ctx("Failed to run MFC\n");
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ mfc_release_instance_context(ctx);
+ return -EIO;
+ }
+
+ if (mfc_wait_for_done_ctx(ctx,
+ MFC_REG_R2H_CMD_OPEN_INSTANCE_RET)) {
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ mfc_release_instance_context(ctx);
+ return -EIO;
+ }
+
+ mfc_release_hwlock_ctx(ctx);
+
+ mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+
+ if (mfc_dec_ctx_ready(ctx))
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ if (mfc_is_work_to_do(dev))
+ queue_work(dev->butler_wq, &dev->butler_work);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Reqeust buffers */
+static int vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec;
+ int ret = 0;
+
+ mfc_debug_enter();
+
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+ mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
+ return -EINVAL;
+ }
+
+ if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src reqbuf(%d)\n", reqbufs->count);
+ /* Can only request buffers after
+ an instance has been opened.*/
+ if (ctx->state == MFCINST_GOT_INST) {
+ if (reqbufs->count == 0) {
+ ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+ ctx->output_state = QUEUE_FREE;
+ return ret;
+ }
+
+ /* Decoding */
+ if (ctx->output_state != QUEUE_FREE) {
+ mfc_err_ctx("Bufs have already been requested\n");
+ return -EINVAL;
+ }
+
+ ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+ if (ret) {
+ mfc_err_ctx("vb2_reqbufs on src failed\n");
+ return ret;
+ }
+
+ ctx->output_state = QUEUE_BUFS_REQUESTED;
+ }
+ } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "dec dst reqbuf(%d)\n", reqbufs->count);
+ if (reqbufs->count == 0) {
+ ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+
+ if (dev->has_mmcache && dev->mmcache.is_on_status)
+ mfc_invalidate_mmcache(dev);
+
+ mfc_release_codec_buffers(ctx);
+ ctx->capture_state = QUEUE_FREE;
+ return ret;
+ }
+
+ dec->dst_memtype = reqbufs->memory;
+
+ if (ctx->capture_state != QUEUE_FREE) {
+ mfc_err_ctx("Bufs have already been requested\n");
+ return -EINVAL;
+ }
+
+ ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ if (ret) {
+ mfc_err_ctx("vb2_reqbufs on capture failed\n");
+ return ret;
+ }
+
+ if (reqbufs->count < ctx->dpb_count) {
+ mfc_err_ctx("Not enough buffers allocated\n");
+ reqbufs->count = 0;
+ vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ return -ENOMEM;
+ }
+
+ dec->total_dpb_count = reqbufs->count;
+
+ ret = mfc_alloc_codec_buffers(ctx);
+ if (ret) {
+ mfc_err_ctx("Failed to allocate decoding buffers\n");
+ reqbufs->count = 0;
+ vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ return -ENOMEM;
+ }
+
+ ctx->capture_state = QUEUE_BUFS_REQUESTED;
+
+ if (mfc_dec_ctx_ready(ctx))
+ mfc_set_bit(ctx->num, &dev->work_bits);
+
+ mfc_try_run(dev);
+ }
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Query buffer */
+static int vidioc_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret;
+
+ mfc_debug_enter();
+
+ if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "dec dst querybuf, state: %d\n", ctx->state);
+ ret = vb2_querybuf(&ctx->vq_dst, buf);
+ if (ret != 0) {
+ mfc_err_dev("dec dst: error in vb2_querybuf()\n");
+ return ret;
+ }
+ } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src querybuf, state: %d\n", ctx->state);
+ ret = vb2_querybuf(&ctx->vq_src, buf);
+ if (ret != 0) {
+ mfc_err_dev("dec src: error in vb2_querybuf()\n");
+ return ret;
+ }
+ } else {
+ mfc_err_dev("invalid buf type (%d)\n", buf->type);
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Queue a buffer */
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = -EINVAL;
+
+ mfc_debug_enter();
+
+ if (ctx->state == MFCINST_ERROR) {
+ mfc_err_ctx("Call on QBUF after unrecoverable error\n");
+ return -EIO;
+ }
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
+ mfc_err_ctx("multiplanar but length is zero\n");
+ return -EIO;
+ }
+
+ if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src buf[%d] Q\n", buf->index);
+ if (buf->m.planes[0].bytesused > buf->m.planes[0].length) {
+ mfc_err_ctx("data size (%d) must be less than "
+ "buffer size(%d)\n",
+ buf->m.planes[0].bytesused,
+ buf->m.planes[0].length);
+ return -EIO;
+ }
+
+ mfc_qos_update_framerate(ctx);
+
+ if (!buf->m.planes[0].bytesused) {
+ buf->m.planes[0].bytesused = buf->m.planes[0].length;
+ mfc_debug(2, "Src size zero, changed to buf size %d\n",
+ buf->m.planes[0].bytesused);
+ } else {
+ mfc_debug(2, "Src size = %d\n", buf->m.planes[0].bytesused);
+ }
+ ret = vb2_qbuf(&ctx->vq_src, buf);
+ } else {
+ mfc_debug(4, "dec dst buf[%d] Q\n", buf->index);
+ ret = vb2_qbuf(&ctx->vq_dst, buf);
+ }
+
+ mfc_debug_leave();
+ return ret;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct dec_dpb_ref_info *dstBuf, *srcBuf;
+ int ret;
+ int ncount = 0;
+
+ mfc_debug_enter();
+
+ if (ctx->state == MFCINST_ERROR) {
+ mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
+ return -EIO;
+ }
+ if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src buf[%d] DQ\n", buf->index);
+ ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+ } else {
+ mfc_debug(4, "dec dst buf[%d] DQ\n", buf->index);
+ ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+
+ if (buf->index >= MFC_MAX_DPBS) {
+ mfc_err_ctx("buffer index[%d] range over\n", buf->index);
+ return -EINVAL;
+ }
+
+ /* Memcpy from dec->ref_info to shared memory */
+ srcBuf = &dec->ref_info[buf->index];
+ for (ncount = 0; ncount < MFC_MAX_DPBS; ncount++) {
+ if (srcBuf->dpb[ncount].fd[0] == MFC_INFO_INIT_FD)
+ break;
+ mfc_debug(2, "[DPB] DQ index[%d] Released FD = %d\n",
+ buf->index, srcBuf->dpb[ncount].fd[0]);
+ }
+
+ if (dec->sh_handle.vaddr != NULL) {
+ dstBuf = (struct dec_dpb_ref_info *)
+ dec->sh_handle.vaddr + buf->index;
+ memcpy(dstBuf, srcBuf, sizeof(struct dec_dpb_ref_info));
+ dstBuf->index = buf->index;
+ }
+ }
+ mfc_debug_leave();
+ return ret;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = -EINVAL;
+
+ mfc_debug_enter();
+
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src streamon\n");
+ ret = vb2_streamon(&ctx->vq_src, type);
+ } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "dec dst streamon\n");
+ ret = vb2_streamon(&ctx->vq_dst, type);
+
+ if (!ret)
+ mfc_qos_on(ctx);
+ } else {
+ mfc_err_ctx("unknown v4l2 buffer type\n");
+ }
+
+ mfc_debug(2, "src: %d, dst: %d, state = %d, dpb_count = %d\n",
+ mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+ mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+ ctx->state, ctx->dpb_count);
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Stream off, which equals to a pause */
+static int vidioc_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = -EINVAL;
+
+ mfc_debug_enter();
+
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src streamoff\n");
+ mfc_qos_reset_last_framerate(ctx);
+
+ ret = vb2_streamoff(&ctx->vq_src, type);
+ } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "dec dst streamoff\n");
+ ret = vb2_streamoff(&ctx->vq_dst, type);
+ if (!ret)
+ mfc_qos_off(ctx);
+ } else {
+ mfc_err_ctx("unknown v4l2 buffer type\n");
+ }
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Query a ctrl */
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ struct v4l2_queryctrl *c;
+
+ c = __mfc_dec_get_ctrl(qc->id);
+ if (!c) {
+ mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
+ return -EINVAL;
+ }
+
+ *qc = *c;
+ return 0;
+}
+
+static int __mfc_dec_ext_info(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ int val = 0;
+
+ val |= DEC_SET_DYNAMIC_DPB;
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
+ val |= DEC_SET_SKYPE_FLAG;
+
+ mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
+
+ return val;
+}
+
+/* Get ctrl */
+static int __mfc_dec_get_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ int found = 0;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+ ctrl->value = dec->loop_filter_mpeg4;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
+ ctrl->value = dec->display_delay;
+ break;
+ case V4L2_CID_CACHEABLE:
+ mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+ break;
+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+ if (ctx->state >= MFCINST_HEAD_PARSED &&
+ ctx->state < MFCINST_ABORT) {
+ ctrl->value = ctx->dpb_count;
+ break;
+ } else if (ctx->state != MFCINST_INIT) {
+ mfc_err_ctx("Decoding not initialised\n");
+ return -EINVAL;
+ }
+
+ /* Should wait for the header to be parsed */
+ if (mfc_wait_for_done_ctx(ctx,
+ MFC_REG_R2H_CMD_SEQ_DONE_RET)) {
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ return -EIO;
+ }
+
+ if (ctx->state >= MFCINST_HEAD_PARSED &&
+ ctx->state < MFCINST_ABORT) {
+ ctrl->value = ctx->dpb_count;
+ } else {
+ mfc_err_ctx("Decoding not initialised\n");
+ return -EINVAL;
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+ ctrl->value = dec->slice_enable;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
+ /* Not used */
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
+ ctrl->value = dec->crc_enable;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
+ if (ctx->is_dpb_realloc && ctx->state == MFCINST_HEAD_PARSED)
+ ctrl->value = MFCSTATE_DEC_S3D_REALLOC;
+ else if (ctx->state == MFCINST_RES_CHANGE_FLUSH
+ || ctx->state == MFCINST_RES_CHANGE_END
+ || ctx->state == MFCINST_HEAD_PARSED)
+ ctrl->value = MFCSTATE_DEC_RES_DETECT;
+ else if (ctx->state == MFCINST_FINISHING)
+ ctrl->value = MFCSTATE_DEC_TERMINATING;
+ else
+ ctrl->value = MFCSTATE_PROCESSING;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
+ ctrl->value = dec->sei_parse;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
+ ctrl->value = dec->idr_decoding;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE:
+ ctrl->value = mfc_qos_get_framerate(ctx);
+ break;
+ case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
+ ctrl->value = dev->pdata->ip_ver;
+ break;
+ case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+ ctrl->value = ctx->qos_ratio;
+ break;
+ case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
+ ctrl->value = dec->is_dynamic_dpb;
+ break;
+ case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
+ ctrl->value = __mfc_dec_ext_info(ctx);
+ break;
+ case V4L2_CID_MPEG_MFC_GET_10BIT_INFO:
+ ctrl->value = ctx->is_10bit;
+ break;
+ case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
+ ctrl->value = MFC_DRIVER_INFO;
+ break;
+ default:
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+
+ if (ctx_ctrl->id == ctrl->id) {
+ if (ctx_ctrl->has_new) {
+ ctx_ctrl->has_new = 0;
+ ctrl->value = ctx_ctrl->val;
+ } else {
+ mfc_debug(5, "[CTRLS] Control value "\
+ "is not up to date: "\
+ "0x%08x\n", ctrl->id);
+ return -EINVAL;
+ }
+
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+ return 0;
+}
+
+/* Get a ctrl */
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = 0;
+
+ mfc_debug_enter();
+ ret = __mfc_dec_get_ctrl_val(ctx, ctrl);
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Set a ctrl */
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ int ret = 0;
+ int found = 0;
+
+ mfc_debug_enter();
+
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ ret = __mfc_dec_check_ctrl_val(ctx, ctrl);
+ if (ret)
+ return ret;
+
+ mfc_debug(5, "[CTRLS] set id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+ dec->loop_filter_mpeg4 = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
+ dec->display_delay = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+ dec->slice_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
+ /* Not used */
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
+ dec->crc_enable = ctrl->value;
+ break;
+ case V4L2_CID_CACHEABLE:
+ mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
+ dec->sei_parse = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
+ dec->idr_decoding = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY:
+ dec->immediate_display = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE:
+ dec->is_dts_mode = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START:
+ ctx->wait_state = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE:
+ mfc_err_dev("[DPB] not supported CID: 0x%x\n",ctrl->id);
+ break;
+ case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+ ctx->qos_ratio = ctrl->value;
+ mfc_info_ctx("[QoS] set %d qos_ratio\n", ctrl->value);
+ break;
+ case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
+ dec->is_dynamic_dpb = ctrl->value;
+ if (dec->is_dynamic_dpb == 0)
+ mfc_err_dev("[DPB] is_dynamic_dpb is 0. it has to be enabled\n");
+ break;
+ case V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE:
+ if (dec->sh_handle.fd == -1) {
+ dec->sh_handle.fd = ctrl->value;
+ if (mfc_mem_get_user_shared_handle(ctx, &dec->sh_handle))
+ return -EINVAL;
+ else
+ mfc_debug(2, "[MEMINFO][DPB] shared handle fd: %d, vaddr: 0x%p\n",
+ dec->sh_handle.fd, dec->sh_handle.vaddr);
+ }
+ break;
+ case V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE:
+ ctx->buf_process_type = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT:
+ dec->detect_black_bar = ctrl->value;
+ break;
+ default:
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
+ continue;
+
+ if (ctx_ctrl->id == ctrl->id) {
+ ctx_ctrl->has_new = 1;
+ ctx_ctrl->val = ctrl->value;
+
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Get cropping information */
+static int vidioc_g_crop(struct file *file, void *priv,
+ struct v4l2_crop *cr)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_dec *dec = ctx->dec_priv;
+
+ mfc_debug_enter();
+
+ if (!ready_to_get_crop(ctx)) {
+ mfc_debug(2, "ready to get crop failed\n");
+ return -EINVAL;
+ }
+
+ if (ctx->state == MFCINST_RUNNING && dec->detect_black_bar
+ && dec->black_bar_updated) {
+ cr->c.left = dec->black_bar.left;
+ cr->c.top = dec->black_bar.top;
+ cr->c.width = dec->black_bar.width;
+ cr->c.height = dec->black_bar.height;
+ mfc_debug(2, "[FRAME][BLACKBAR] Cropping info: l=%d t=%d w=%d h=%d\n",
+ dec->black_bar.left,
+ dec->black_bar.top,
+ dec->black_bar.width,
+ dec->black_bar.height);
+ } else {
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264 ||
+ ctx->src_fmt->fourcc == V4L2_PIX_FMT_HEVC ||
+ ctx->src_fmt->fourcc == V4L2_PIX_FMT_BPG) {
+ cr->c.left = dec->cr_left;
+ cr->c.top = dec->cr_top;
+ cr->c.width = ctx->img_width - dec->cr_left - dec->cr_right;
+ cr->c.height = ctx->img_height - dec->cr_top - dec->cr_bot;
+ mfc_debug(2, "[FRAME] Cropping info: l=%d t=%d " \
+ "w=%d h=%d (r=%d b=%d fw=%d fh=%d)\n",
+ dec->cr_left, dec->cr_top,
+ cr->c.width, cr->c.height,
+ dec->cr_right, dec->cr_bot,
+ ctx->img_width, ctx->img_height);
+ } else {
+ cr->c.left = 0;
+ cr->c.top = 0;
+ cr->c.width = ctx->img_width;
+ cr->c.height = ctx->img_height;
+ mfc_debug(2, "[FRAME] Cropping info: w=%d h=%d fw=%d fh=%d\n",
+ cr->c.width, cr->c.height,
+ ctx->img_width, ctx->img_height);
+ }
+ }
+
+ mfc_debug_leave();
+ return 0;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+ struct v4l2_ext_controls *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct v4l2_ext_control *ext_ctrl;
+ struct v4l2_control ctrl;
+ int i;
+ int ret = 0;
+
+ if (f->which != V4L2_CTRL_CLASS_MPEG)
+ return -EINVAL;
+
+ for (i = 0; i < f->count; i++) {
+ ext_ctrl = (f->controls + i);
+
+ ctrl.id = ext_ctrl->id;
+
+ ret = __mfc_dec_get_ctrl_val(ctx, &ctrl);
+ if (ret == 0) {
+ ext_ctrl->value = ctrl.value;
+ } else {
+ f->error_idx = i;
+ break;
+ }
+
+ mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
+ i, ext_ctrl->id, ext_ctrl->value);
+ }
+
+ return ret;
+}
+
+/* v4l2_ioctl_ops */
+static const struct v4l2_ioctl_ops mfc_dec_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+ .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+ .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap_mplane,
+ .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out_mplane,
+ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
+ .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
+ .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane,
+ .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out_mplane,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
+};
+
+const struct v4l2_ioctl_ops *mfc_get_dec_v4l2_ioctl_ops(void)
+{
+ return &mfc_dec_ioctl_ops;
+}
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_dec_v4l2.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_DEC_V4L2_H
+#define __MFC_DEC_V4L2_H __FILE__
+
+#include "mfc_common.h"
+
+const struct v4l2_ioctl_ops *mfc_get_dec_v4l2_ioctl_ops(void);
+
+#endif /* __MFC_DEC_V4L2_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_common.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static int mfc_dec_queue_setup(struct vb2_queue *vq,
+ unsigned int *buf_count, unsigned int *plane_count,
+ unsigned int psize[], struct device *alloc_devs[])
+{
+ struct mfc_ctx *ctx;
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ struct mfc_raw_info *raw;
+ int i;
+
+ mfc_debug_enter();
+
+ if (!vq) {
+ mfc_err_dev("no vb2_queue info\n");
+ return -EINVAL;
+ }
+
+ ctx = vq->drv_priv;
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ raw = &ctx->raw_buf;
+
+ /* Video output for decoding (source)
+ * this can be set after getting an instance */
+ if (ctx->state == MFCINST_GOT_INST &&
+ vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "dec src\n");
+ /* A single plane is required for input */
+ *plane_count = 1;
+ if (*buf_count < 1)
+ *buf_count = 1;
+ if (*buf_count > MFC_MAX_BUFFERS)
+ *buf_count = MFC_MAX_BUFFERS;
+
+ psize[0] = dec->src_buf_size;
+ alloc_devs[0] = dev->device;
+ /* Video capture for decoding (destination)
+ * this can be set after the header was parsed */
+ } else if (ctx->state == MFCINST_HEAD_PARSED &&
+ vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "dec dst\n");
+ /* Output plane count is different by the pixel format */
+ *plane_count = ctx->dst_fmt->mem_planes;
+ /* Setup buffer count */
+ if (*buf_count < ctx->dpb_count)
+ *buf_count = ctx->dpb_count;
+ if (*buf_count > MFC_MAX_BUFFERS)
+ *buf_count = MFC_MAX_BUFFERS;
+
+ if (ctx->dst_fmt->mem_planes == 1) {
+ psize[0] = raw->total_plane_size;
+ alloc_devs[0] = dev->device;
+ } else {
+ for (i = 0; i < ctx->dst_fmt->num_planes; i++) {
+ psize[i] = raw->plane_size[i];
+ alloc_devs[i] = dev->device;
+ }
+ }
+ } else {
+ mfc_err_ctx("State seems invalid. State = %d, vq->type = %d\n",
+ ctx->state, vq->type);
+ return -EINVAL;
+ }
+
+ mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
+ *buf_count, *plane_count, vq->type);
+ for (i = 0; i < *plane_count; i++)
+ mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static void mfc_dec_unlock(struct vb2_queue *q)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return;
+ }
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return;
+ }
+
+ mutex_unlock(&dev->mfc_mutex);
+}
+
+static void mfc_dec_lock(struct vb2_queue *q)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return;
+ }
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return;
+ }
+
+ mutex_lock(&dev->mfc_mutex);
+}
+
+static int mfc_dec_buf_init(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ struct mfc_buf *buf = vb_to_mfc_buf(vb);
+ dma_addr_t start_raw;
+ int i, ret;
+
+ mfc_debug_enter();
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
+ if (ret < 0)
+ return ret;
+
+ start_raw = mfc_mem_get_daddr_vb(vb, 0);
+ if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
+ buf->addr[0][0] = start_raw;
+ buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N_10B) {
+ buf->addr[0][0] = start_raw;
+ buf->addr[0][1] = NV12N_10B_CBCR_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
+ buf->addr[0][0] = start_raw;
+ buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ } else {
+ for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
+ buf->addr[0][i] = mfc_mem_get_daddr_vb(vb, i);
+ }
+
+ if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
+ vb->index) < 0)
+ mfc_err_ctx("failed in init_buf_ctrls\n");
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ ret = mfc_check_vb_with_fmt(ctx->src_fmt, vb);
+ if (ret < 0)
+ return ret;
+
+ buf->addr[0][0] = mfc_mem_get_daddr_vb(vb, 0);
+
+ if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
+ vb->index) < 0)
+ mfc_err_ctx("failed in init_buf_ctrls\n");
+ } else {
+ mfc_err_ctx("mfc_dec_buf_init: unknown queue type\n");
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int mfc_dec_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ struct mfc_dec *dec;
+ struct mfc_raw_info *raw;
+ unsigned int index = vb->index;
+ size_t buf_size;
+ int i;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ raw = &ctx->raw_buf;
+ /* check the size per plane */
+ if (ctx->dst_fmt->mem_planes == 1) {
+ buf_size = vb2_plane_size(vb, 0);
+ mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
+ buf_size, raw->total_plane_size);
+ if (buf_size < raw->total_plane_size) {
+ mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
+ buf_size, raw->total_plane_size);
+ return -EINVAL;
+ }
+ } else {
+ for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
+ buf_size = vb2_plane_size(vb, i);
+ mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
+ i, buf_size, raw->plane_size[i]);
+ if (buf_size < raw->plane_size[i]) {
+ mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
+ i, buf_size, raw->plane_size[i]);
+ return -EINVAL;
+ }
+ }
+ }
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ buf_size = vb2_plane_size(vb, 0);
+ mfc_debug(2, "[STREAM] vb size: %lu, calc size: %d\n",
+ buf_size, dec->src_buf_size);
+
+ if (buf_size < dec->src_buf_size) {
+ mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
+ buf_size, dec->src_buf_size);
+ return -EINVAL;
+ }
+
+ if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in to_buf_ctrls\n");
+ }
+
+ return 0;
+}
+
+static void mfc_dec_buf_finish(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ unsigned int index = vb->index;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return;
+ }
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
+ mfc_err_ctx("failed in to_ctx_ctrls\n");
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in to_ctx_ctrls\n");
+ }
+}
+
+static void mfc_dec_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ unsigned int index = vb->index;
+
+ mfc_debug_enter();
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return;
+ }
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+ MFC_CTRL_TYPE_DST, index) < 0)
+ mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+ MFC_CTRL_TYPE_SRC, index) < 0)
+ mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+ } else {
+ mfc_err_ctx("mfc_dec_buf_cleanup: unknown queue type\n");
+ }
+
+ mfc_debug_leave();
+}
+
+static int mfc_dec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+
+ if (ctx->state == MFCINST_FINISHING)
+ mfc_change_state(ctx, MFCINST_RUNNING);
+
+ /* If context is ready then dev = work->data;schedule it to run */
+ if (mfc_dec_ctx_ready(ctx)) {
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ }
+
+ mfc_try_run(dev);
+
+ return 0;
+}
+
+static void __mfc_dec_src_stop_streaming(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ struct mfc_buf *src_mb;
+ int index, csd, condition = 0;
+ int ret = 0;
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return;
+ }
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return;
+ }
+
+ while (1) {
+ csd = mfc_peek_buf_csd(&ctx->buf_queue_lock, &ctx->src_buf_queue);
+
+ if (csd == 1) {
+ mfc_clean_ctx_int_flags(ctx);
+ if (need_to_special_parsing(ctx)) {
+ mfc_change_state(ctx, MFCINST_SPECIAL_PARSING);
+ condition = MFC_REG_R2H_CMD_SEQ_DONE_RET;
+ mfc_info_ctx("try to special parsing! (before NAL_START)\n");
+ } else if (need_to_special_parsing_nal(ctx)) {
+ mfc_change_state(ctx, MFCINST_SPECIAL_PARSING_NAL);
+ condition = MFC_REG_R2H_CMD_FRAME_DONE_RET;
+ mfc_info_ctx("try to special parsing! (after NAL_START)\n");
+ } else {
+ mfc_info_ctx("can't parsing CSD!, state = %d\n", ctx->state);
+ }
+
+ if (condition) {
+ mfc_set_bit(ctx->num, &dev->work_bits);
+
+ ret = mfc_just_run(dev, ctx->num);
+ if (ret) {
+ mfc_err_ctx("Failed to run MFC\n");
+ } else {
+ if (mfc_wait_for_done_ctx(ctx, condition))
+ mfc_err_ctx("special parsing time out\n");
+ }
+ }
+ }
+
+ src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (!src_mb)
+ break;
+
+ index = src_mb->vb.vb2_buf.index;
+
+ if (ctx->is_drm)
+ mfc_stream_unprotect(ctx, src_mb, index);
+ vb2_set_plane_payload(&src_mb->vb.vb2_buf, 0, 0);
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
+
+ dec->consumed = 0;
+ dec->remained_size = 0;
+ ctx->check_dump = 0;
+
+ mfc_init_queue(&ctx->src_buf_queue);
+
+ index = 0;
+ while (index < MFC_MAX_BUFFERS) {
+ index = find_next_bit(&ctx->src_ctrls_avail,
+ MFC_MAX_BUFFERS, index);
+ if (index < MFC_MAX_BUFFERS)
+ call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
+ index++;
+ }
+}
+
+static void __mfc_dec_dst_stop_streaming(struct mfc_ctx *ctx)
+{
+ struct mfc_dec *dec;
+ int index = 0;
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return;
+ }
+
+ mfc_cleanup_assigned_fd(ctx);
+ mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->ref_buf_queue);
+
+ dec->dynamic_used = 0;
+ dec->err_reuse_flag = 0;
+ dec->dec_only_release_flag = 0;
+
+ mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
+
+ ctx->is_dpb_realloc = 0;
+ dec->available_dpb = 0;
+
+ dec->y_addr_for_pb = 0;
+
+ mfc_cleanup_assigned_dpb(ctx);
+
+ while (index < MFC_MAX_BUFFERS) {
+ index = find_next_bit(&ctx->dst_ctrls_avail,
+ MFC_MAX_BUFFERS, index);
+ if (index < MFC_MAX_BUFFERS)
+ call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
+ index++;
+ }
+
+ if (ctx->wait_state == WAIT_INITBUF_DONE ||
+ ctx->wait_state == WAIT_DECODING) {
+ ctx->wait_state = WAIT_NONE;
+ mfc_debug(2, "Decoding can be started now\n");
+ }
+}
+
+static void mfc_dec_stop_streaming(struct vb2_queue *q)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev;
+ int ret = 0;
+ int prev_state;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return;
+ }
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return;
+ }
+
+ mfc_info_ctx("dec stop_streaming is called, hwlock : %d, type : %d\n",
+ test_bit(ctx->num, &dev->hwlock.bits), q->type);
+ MFC_TRACE_CTX("** DEC streamoff(type:%d)\n", q->type);
+
+ MFC_TRACE_CTX_HWLOCK("**DEC streamoff(type:%d)\n", q->type);
+ /* If a H/W operation is in progress, wait for it complete */
+ ret = mfc_get_hwlock_ctx(ctx);
+ if (ret < 0) {
+ mfc_err_ctx("Failed to get hwlock\n");
+ return;
+ }
+
+ if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ __mfc_dec_dst_stop_streaming(ctx);
+ else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ __mfc_dec_src_stop_streaming(ctx);
+
+ if (ctx->state == MFCINST_FINISHING)
+ mfc_change_state(ctx, MFCINST_RUNNING);
+
+ if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && need_to_dpb_flush(ctx)) {
+ prev_state = ctx->state;
+ mfc_change_state(ctx, MFCINST_DPB_FLUSHING);
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ mfc_clean_ctx_int_flags(ctx);
+ mfc_info_ctx("try to DPB flush\n");
+ ret = mfc_just_run(dev, ctx->num);
+ if (ret) {
+ mfc_err_ctx("Failed to run MFC\n");
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ return;
+ }
+
+ if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_DPB_FLUSH_RET)) {
+ mfc_err_ctx("time out during DPB flush\n");
+ dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_DPB_FLUSH);
+ call_dop(dev, dump_and_stop_always, dev);
+ }
+
+ mfc_change_state(ctx, prev_state);
+ }
+
+ mfc_debug(2, "buffer cleanup & flush is done in stop_streaming, type : %d\n", q->type);
+
+ mfc_clear_bit(ctx->num, &dev->work_bits);
+ mfc_release_hwlock_ctx(ctx);
+
+ if (mfc_dec_ctx_ready(ctx))
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ if (mfc_is_work_to_do(dev))
+ queue_work(dev->butler_wq, &dev->butler_work);
+}
+
+static void mfc_dec_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ struct mfc_buf *buf = vb_to_mfc_buf(vb);
+ int i;
+ unsigned char *stream_vir = NULL;
+
+ mfc_debug_enter();
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return;
+ }
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return;
+ }
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return;
+ }
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(2, "[BUFINFO] ctx[%d] add src index:%d, addr: 0x%08llx\n",
+ ctx->num, vb->index, buf->addr[0][0]);
+ if (dec->dst_memtype == V4L2_MEMORY_DMABUF &&
+ ctx->state < MFCINST_HEAD_PARSED && !ctx->is_drm)
+ stream_vir = vb2_plane_vaddr(vb, 0);
+
+ buf->vir_addr = stream_vir;
+
+ mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
+
+ MFC_TRACE_CTX("Q src[%d] fd: %d, %#llx\n",
+ vb->index, vb->planes[0].m.fd, buf->addr[0][0]);
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
+ mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr[%d]: 0x%08llx\n",
+ ctx->num, vb->index, i, buf->addr[0][i]);
+ mfc_store_dpb(ctx, vb);
+
+ if ((dec->dst_memtype == V4L2_MEMORY_USERPTR || dec->dst_memtype == V4L2_MEMORY_DMABUF) &&
+ mfc_is_queue_count_same(&ctx->buf_queue_lock,
+ &ctx->dst_buf_queue, dec->total_dpb_count))
+ ctx->capture_state = QUEUE_BUFS_MMAPED;
+
+ MFC_TRACE_CTX("Q dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
+ vb->index, vb->planes[0].m.fd, buf->addr[0][0],
+ dec->available_dpb, dec->dynamic_used);
+ } else {
+ mfc_err_ctx("Unsupported buffer type (%d)\n", vq->type);
+ }
+
+ if (mfc_dec_ctx_ready(ctx)) {
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ mfc_try_run(dev);
+ }
+
+ mfc_debug_leave();
+}
+
+struct vb2_ops mfc_dec_qops = {
+ .queue_setup = mfc_dec_queue_setup,
+ .wait_prepare = mfc_dec_unlock,
+ .wait_finish = mfc_dec_lock,
+ .buf_init = mfc_dec_buf_init,
+ .buf_prepare = mfc_dec_buf_prepare,
+ .buf_finish = mfc_dec_buf_finish,
+ .buf_cleanup = mfc_dec_buf_cleanup,
+ .start_streaming = mfc_dec_start_streaming,
+ .stop_streaming = mfc_dec_stop_streaming,
+ .buf_queue = mfc_dec_buf_queue,
+};
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_common.h"
-
-#include "mfc_hwlock.h"
-#include "mfc_nal_q.h"
-#include "mfc_opr.h"
-#include "mfc_sync.h"
-
-#include "mfc_queue.h"
-#include "mfc_utils.h"
-#include "mfc_buf.h"
-#include "mfc_mem.h"
-
-static int mfc_dec_queue_setup(struct vb2_queue *vq,
- unsigned int *buf_count, unsigned int *plane_count,
- unsigned int psize[], struct device *alloc_devs[])
-{
- struct mfc_ctx *ctx;
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- struct mfc_raw_info *raw;
- int i;
-
- mfc_debug_enter();
-
- if (!vq) {
- mfc_err_dev("no vb2_queue info\n");
- return -EINVAL;
- }
-
- ctx = vq->drv_priv;
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- raw = &ctx->raw_buf;
-
- /* Video output for decoding (source)
- * this can be set after getting an instance */
- if (ctx->state == MFCINST_GOT_INST &&
- vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "dec src\n");
- /* A single plane is required for input */
- *plane_count = 1;
- if (*buf_count < 1)
- *buf_count = 1;
- if (*buf_count > MFC_MAX_BUFFERS)
- *buf_count = MFC_MAX_BUFFERS;
-
- psize[0] = dec->src_buf_size;
- alloc_devs[0] = dev->device;
- /* Video capture for decoding (destination)
- * this can be set after the header was parsed */
- } else if (ctx->state == MFCINST_HEAD_PARSED &&
- vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "dec dst\n");
- /* Output plane count is different by the pixel format */
- *plane_count = ctx->dst_fmt->mem_planes;
- /* Setup buffer count */
- if (*buf_count < ctx->dpb_count)
- *buf_count = ctx->dpb_count;
- if (*buf_count > MFC_MAX_BUFFERS)
- *buf_count = MFC_MAX_BUFFERS;
-
- if (ctx->dst_fmt->mem_planes == 1) {
- psize[0] = raw->total_plane_size;
- alloc_devs[0] = dev->device;
- } else {
- for (i = 0; i < ctx->dst_fmt->num_planes; i++) {
- psize[i] = raw->plane_size[i];
- alloc_devs[i] = dev->device;
- }
- }
- } else {
- mfc_err_ctx("State seems invalid. State = %d, vq->type = %d\n",
- ctx->state, vq->type);
- return -EINVAL;
- }
-
- mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
- *buf_count, *plane_count, vq->type);
- for (i = 0; i < *plane_count; i++)
- mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static void mfc_dec_unlock(struct vb2_queue *q)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return;
- }
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return;
- }
-
- mutex_unlock(&dev->mfc_mutex);
-}
-
-static void mfc_dec_lock(struct vb2_queue *q)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return;
- }
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return;
- }
-
- mutex_lock(&dev->mfc_mutex);
-}
-
-static int mfc_dec_buf_init(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- struct mfc_buf *buf = vb_to_mfc_buf(vb);
- dma_addr_t start_raw;
- int i, ret;
-
- mfc_debug_enter();
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- ret = mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
- if (ret < 0)
- return ret;
-
- start_raw = mfc_mem_get_daddr_vb(vb, 0);
- if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
- buf->addr[0][0] = start_raw;
- buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N_10B) {
- buf->addr[0][0] = start_raw;
- buf->addr[0][1] = NV12N_10B_CBCR_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
- buf->addr[0][0] = start_raw;
- buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- } else {
- for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
- buf->addr[0][i] = mfc_mem_get_daddr_vb(vb, i);
- }
-
- if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
- vb->index) < 0)
- mfc_err_ctx("failed in init_buf_ctrls\n");
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- ret = mfc_check_vb_with_fmt(ctx->src_fmt, vb);
- if (ret < 0)
- return ret;
-
- buf->addr[0][0] = mfc_mem_get_daddr_vb(vb, 0);
-
- if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
- vb->index) < 0)
- mfc_err_ctx("failed in init_buf_ctrls\n");
- } else {
- mfc_err_ctx("mfc_dec_buf_init: unknown queue type\n");
- return -EINVAL;
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int mfc_dec_buf_prepare(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- struct mfc_dec *dec;
- struct mfc_raw_info *raw;
- unsigned int index = vb->index;
- size_t buf_size;
- int i;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- raw = &ctx->raw_buf;
- /* check the size per plane */
- if (ctx->dst_fmt->mem_planes == 1) {
- buf_size = vb2_plane_size(vb, 0);
- mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
- buf_size, raw->total_plane_size);
- if (buf_size < raw->total_plane_size) {
- mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
- buf_size, raw->total_plane_size);
- return -EINVAL;
- }
- } else {
- for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
- buf_size = vb2_plane_size(vb, i);
- mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
- i, buf_size, raw->plane_size[i]);
- if (buf_size < raw->plane_size[i]) {
- mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
- i, buf_size, raw->plane_size[i]);
- return -EINVAL;
- }
- }
- }
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- buf_size = vb2_plane_size(vb, 0);
- mfc_debug(2, "[STREAM] vb size: %lu, calc size: %d\n",
- buf_size, dec->src_buf_size);
-
- if (buf_size < dec->src_buf_size) {
- mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
- buf_size, dec->src_buf_size);
- return -EINVAL;
- }
-
- if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in to_buf_ctrls\n");
- }
-
- return 0;
-}
-
-static void mfc_dec_buf_finish(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- unsigned int index = vb->index;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return;
- }
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
- mfc_err_ctx("failed in to_ctx_ctrls\n");
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in to_ctx_ctrls\n");
- }
-}
-
-static void mfc_dec_buf_cleanup(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- unsigned int index = vb->index;
-
- mfc_debug_enter();
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return;
- }
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- if (call_cop(ctx, cleanup_buf_ctrls, ctx,
- MFC_CTRL_TYPE_DST, index) < 0)
- mfc_err_ctx("failed in cleanup_buf_ctrls\n");
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (call_cop(ctx, cleanup_buf_ctrls, ctx,
- MFC_CTRL_TYPE_SRC, index) < 0)
- mfc_err_ctx("failed in cleanup_buf_ctrls\n");
- } else {
- mfc_err_ctx("mfc_dec_buf_cleanup: unknown queue type\n");
- }
-
- mfc_debug_leave();
-}
-
-static int mfc_dec_start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
-
- if (ctx->state == MFCINST_FINISHING)
- mfc_change_state(ctx, MFCINST_RUNNING);
-
- /* If context is ready then dev = work->data;schedule it to run */
- if (mfc_dec_ctx_ready(ctx)) {
- mfc_set_bit(ctx->num, &dev->work_bits);
- }
-
- mfc_try_run(dev);
-
- return 0;
-}
-
-static void __mfc_dec_src_stop_streaming(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- struct mfc_buf *src_mb;
- int index, csd, condition = 0;
- int ret = 0;
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return;
- }
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return;
- }
-
- while (1) {
- csd = mfc_peek_buf_csd(&ctx->buf_queue_lock, &ctx->src_buf_queue);
-
- if (csd == 1) {
- mfc_clean_ctx_int_flags(ctx);
- if (need_to_special_parsing(ctx)) {
- mfc_change_state(ctx, MFCINST_SPECIAL_PARSING);
- condition = MFC_REG_R2H_CMD_SEQ_DONE_RET;
- mfc_info_ctx("try to special parsing! (before NAL_START)\n");
- } else if (need_to_special_parsing_nal(ctx)) {
- mfc_change_state(ctx, MFCINST_SPECIAL_PARSING_NAL);
- condition = MFC_REG_R2H_CMD_FRAME_DONE_RET;
- mfc_info_ctx("try to special parsing! (after NAL_START)\n");
- } else {
- mfc_info_ctx("can't parsing CSD!, state = %d\n", ctx->state);
- }
-
- if (condition) {
- mfc_set_bit(ctx->num, &dev->work_bits);
-
- ret = mfc_just_run(dev, ctx->num);
- if (ret) {
- mfc_err_ctx("Failed to run MFC\n");
- } else {
- if (mfc_wait_for_done_ctx(ctx, condition))
- mfc_err_ctx("special parsing time out\n");
- }
- }
- }
-
- src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (!src_mb)
- break;
-
- index = src_mb->vb.vb2_buf.index;
-
- if (ctx->is_drm)
- mfc_stream_unprotect(ctx, src_mb, index);
- vb2_set_plane_payload(&src_mb->vb.vb2_buf, 0, 0);
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- }
-
- dec->consumed = 0;
- dec->remained_size = 0;
- ctx->check_dump = 0;
-
- mfc_init_queue(&ctx->src_buf_queue);
-
- index = 0;
- while (index < MFC_MAX_BUFFERS) {
- index = find_next_bit(&ctx->src_ctrls_avail,
- MFC_MAX_BUFFERS, index);
- if (index < MFC_MAX_BUFFERS)
- call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
- index++;
- }
-}
-
-static void __mfc_dec_dst_stop_streaming(struct mfc_ctx *ctx)
-{
- struct mfc_dec *dec;
- int index = 0;
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return;
- }
-
- mfc_cleanup_assigned_fd(ctx);
- mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->ref_buf_queue);
-
- dec->dynamic_used = 0;
- dec->err_reuse_flag = 0;
- dec->dec_only_release_flag = 0;
-
- mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
-
- ctx->is_dpb_realloc = 0;
- dec->available_dpb = 0;
-
- dec->y_addr_for_pb = 0;
-
- mfc_cleanup_assigned_dpb(ctx);
-
- while (index < MFC_MAX_BUFFERS) {
- index = find_next_bit(&ctx->dst_ctrls_avail,
- MFC_MAX_BUFFERS, index);
- if (index < MFC_MAX_BUFFERS)
- call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
- index++;
- }
-
- if (ctx->wait_state == WAIT_INITBUF_DONE ||
- ctx->wait_state == WAIT_DECODING) {
- ctx->wait_state = WAIT_NONE;
- mfc_debug(2, "Decoding can be started now\n");
- }
-}
-
-static void mfc_dec_stop_streaming(struct vb2_queue *q)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev;
- int ret = 0;
- int prev_state;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return;
- }
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return;
- }
-
- mfc_info_ctx("dec stop_streaming is called, hwlock : %d, type : %d\n",
- test_bit(ctx->num, &dev->hwlock.bits), q->type);
- MFC_TRACE_CTX("** DEC streamoff(type:%d)\n", q->type);
-
- MFC_TRACE_CTX_HWLOCK("**DEC streamoff(type:%d)\n", q->type);
- /* If a H/W operation is in progress, wait for it complete */
- ret = mfc_get_hwlock_ctx(ctx);
- if (ret < 0) {
- mfc_err_ctx("Failed to get hwlock\n");
- return;
- }
-
- if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- __mfc_dec_dst_stop_streaming(ctx);
- else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- __mfc_dec_src_stop_streaming(ctx);
-
- if (ctx->state == MFCINST_FINISHING)
- mfc_change_state(ctx, MFCINST_RUNNING);
-
- if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && need_to_dpb_flush(ctx)) {
- prev_state = ctx->state;
- mfc_change_state(ctx, MFCINST_DPB_FLUSHING);
- mfc_set_bit(ctx->num, &dev->work_bits);
- mfc_clean_ctx_int_flags(ctx);
- mfc_info_ctx("try to DPB flush\n");
- ret = mfc_just_run(dev, ctx->num);
- if (ret) {
- mfc_err_ctx("Failed to run MFC\n");
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- return;
- }
-
- if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_DPB_FLUSH_RET)) {
- mfc_err_ctx("time out during DPB flush\n");
- dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_DPB_FLUSH);
- call_dop(dev, dump_and_stop_always, dev);
- }
-
- mfc_change_state(ctx, prev_state);
- }
-
- mfc_debug(2, "buffer cleanup & flush is done in stop_streaming, type : %d\n", q->type);
-
- mfc_clear_bit(ctx->num, &dev->work_bits);
- mfc_release_hwlock_ctx(ctx);
-
- if (mfc_dec_ctx_ready(ctx))
- mfc_set_bit(ctx->num, &dev->work_bits);
- if (mfc_is_work_to_do(dev))
- queue_work(dev->butler_wq, &dev->butler_work);
-}
-
-static void mfc_dec_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- struct mfc_buf *buf = vb_to_mfc_buf(vb);
- int i;
- unsigned char *stream_vir = NULL;
-
- mfc_debug_enter();
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return;
- }
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return;
- }
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return;
- }
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(2, "[BUFINFO] ctx[%d] add src index:%d, addr: 0x%08llx\n",
- ctx->num, vb->index, buf->addr[0][0]);
- if (dec->dst_memtype == V4L2_MEMORY_DMABUF &&
- ctx->state < MFCINST_HEAD_PARSED && !ctx->is_drm)
- stream_vir = vb2_plane_vaddr(vb, 0);
-
- buf->vir_addr = stream_vir;
-
- mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
-
- MFC_TRACE_CTX("Q src[%d] fd: %d, %#llx\n",
- vb->index, vb->planes[0].m.fd, buf->addr[0][0]);
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
- mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr[%d]: 0x%08llx\n",
- ctx->num, vb->index, i, buf->addr[0][i]);
- mfc_store_dpb(ctx, vb);
-
- if ((dec->dst_memtype == V4L2_MEMORY_USERPTR || dec->dst_memtype == V4L2_MEMORY_DMABUF) &&
- mfc_is_queue_count_same(&ctx->buf_queue_lock,
- &ctx->dst_buf_queue, dec->total_dpb_count))
- ctx->capture_state = QUEUE_BUFS_MMAPED;
-
- MFC_TRACE_CTX("Q dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
- vb->index, vb->planes[0].m.fd, buf->addr[0][0],
- dec->available_dpb, dec->dynamic_used);
- } else {
- mfc_err_ctx("Unsupported buffer type (%d)\n", vq->type);
- }
-
- if (mfc_dec_ctx_ready(ctx)) {
- mfc_set_bit(ctx->num, &dev->work_bits);
- mfc_try_run(dev);
- }
-
- mfc_debug_leave();
-}
-
-struct vb2_ops mfc_dec_qops = {
- .queue_setup = mfc_dec_queue_setup,
- .wait_prepare = mfc_dec_unlock,
- .wait_finish = mfc_dec_lock,
- .buf_init = mfc_dec_buf_init,
- .buf_prepare = mfc_dec_buf_prepare,
- .buf_finish = mfc_dec_buf_finish,
- .buf_cleanup = mfc_dec_buf_cleanup,
- .start_streaming = mfc_dec_start_streaming,
- .stop_streaming = mfc_dec_stop_streaming,
- .buf_queue = mfc_dec_buf_queue,
-};
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_enc.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_enc.h"
-#include "mfc_enc_internal.h"
-
-#include "mfc_hwlock.h"
-#include "mfc_otf.h"
-#include "mfc_opr.h"
-#include "mfc_sync.h"
-
-#include "mfc_qos.h"
-#include "mfc_queue.h"
-#include "mfc_utils.h"
-#include "mfc_buf.h"
-#include "mfc_mem.h"
-
-static struct mfc_fmt *__mfc_enc_find_format(struct mfc_ctx *ctx,
- unsigned int pixelformat)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_fmt *fmt = NULL;
- unsigned long i;
-
- for (i = 0; i < NUM_FORMATS; i++) {
- if (enc_formats[i].fourcc == pixelformat) {
- fmt = (struct mfc_fmt *)&enc_formats[i];
- break;
- }
- }
-
- if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
- mfc_err_ctx("[FRAME] 10bit is not supported\n");
- fmt = NULL;
- }
- if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
- mfc_err_ctx("[FRAME] 422 is not supported\n");
- fmt = NULL;
- }
- if (!dev->pdata->support_rgb && (fmt->type & MFC_FMT_RGB)) {
- mfc_err_ctx("[FRAME] RGB is not supported\n");
- fmt = NULL;
- }
-
- return fmt;
-}
-
-static struct v4l2_queryctrl *__mfc_enc_get_ctrl(int id)
-{
- unsigned long i;
-
- for (i = 0; i < NUM_CTRLS; ++i)
- if (id == controls[i].id)
- return &controls[i];
- return NULL;
-}
-
-static int __mfc_enc_check_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct v4l2_queryctrl *c;
-
- c = __mfc_enc_get_ctrl(ctrl->id);
- if (!c) {
- mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
- return -EINVAL;
- }
-
- if (ctrl->id == V4L2_CID_MPEG_VIDEO_GOP_SIZE
- && ctrl->value > c->maximum) {
- mfc_info_ctx("GOP_SIZE is changed to max(%d -> %d)\n",
- ctrl->value, c->maximum);
- ctrl->value = c->maximum;
- }
-
- if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER) {
- if ((ctrl->value & ~(1 << 16)) < c->minimum || (ctrl->value & ~(1 << 16)) > c->maximum
- || (c->step != 0 && (ctrl->value & ~(1 << 16)) % c->step != 0)) {
- mfc_err_ctx("[CTRLS][HIERARCHICAL] Invalid control value for %#x (%#x)\n",
- ctrl->id, ctrl->value);
- return -ERANGE;
- } else {
- return 0;
- }
- }
-
- if (ctrl->value < c->minimum || ctrl->value > c->maximum
- || (c->step != 0 && ctrl->value % c->step != 0)) {
- mfc_err_ctx("[CTRLS] Invalid control value for %#x (%#x)\n",
- ctrl->id, ctrl->value);
- return -ERANGE;
- }
-
- return 0;
-}
-
-static inline int __mfc_enc_h264_profile(struct mfc_ctx *ctx, int profile)
-{
- int ret = 0;
-
- switch (profile) {
- case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
- ret = MFC_REG_E_PROFILE_H264_MAIN;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
- ret = MFC_REG_E_PROFILE_H264_HIGH;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
- ret = MFC_REG_E_PROFILE_H264_BASELINE;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
- ret = MFC_REG_E_PROFILE_H264_CONSTRAINED_BASELINE;
- break;
- case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
- ret = MFC_REG_E_PROFILE_H264_CONSTRAINED_HIGH;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-/* Query capabilities of the device */
-static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
- strncpy(cap->card, "encoder", sizeof(cap->card) - 1);
- cap->bus_info[0] = 0;
- cap->version = KERNEL_VERSION(1, 0, 0);
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
- | V4L2_CAP_VIDEO_OUTPUT
- | V4L2_CAP_VIDEO_CAPTURE_MPLANE
- | V4L2_CAP_VIDEO_OUTPUT_MPLANE
- | V4L2_CAP_STREAMING
- | V4L2_CAP_DEVICE_CAPS;
-
- cap->capabilities = cap->device_caps;
-
- return 0;
-}
-
-static int __mfc_enc_enum_fmt(struct mfc_dev *dev, struct v4l2_fmtdesc *f,
- unsigned int type)
-{
- struct mfc_fmt *fmt;
- unsigned long i, j = 0;
-
- for (i = 0; i < NUM_FORMATS; ++i) {
- if (!(enc_formats[i].type & type))
- continue;
- if (!dev->pdata->support_10bit && (enc_formats[i].type & MFC_FMT_10BIT))
- continue;
- if (!dev->pdata->support_422 && (enc_formats[i].type & MFC_FMT_422))
- continue;
- if (!dev->pdata->support_rgb && (enc_formats[i].type & MFC_FMT_RGB))
- continue;
-
- if (j == f->index) {
- fmt = &enc_formats[i];
- strlcpy(f->description, fmt->name,
- sizeof(f->description));
- f->pixelformat = fmt->fourcc;
-
- return 0;
- }
-
- ++j;
- }
-
- return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
- struct v4l2_fmtdesc *f)
-{
- struct mfc_dev *dev = video_drvdata(file);
-
- return __mfc_enc_enum_fmt(dev, f, MFC_FMT_STREAM);
-}
-
-static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
- struct v4l2_fmtdesc *f)
-{
- struct mfc_dev *dev = video_drvdata(file);
-
- return __mfc_enc_enum_fmt(dev, f, MFC_FMT_FRAME);
-}
-
-static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_enc *enc = ctx->enc_priv;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
- struct mfc_raw_info *raw;
- int i;
-
- mfc_debug_enter();
-
- if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "enc dst g_fmt\n");
- /* This is run on output (encoder dest) */
- pix_fmt_mp->width = 0;
- pix_fmt_mp->height = 0;
- pix_fmt_mp->field = V4L2_FIELD_NONE;
- pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
- pix_fmt_mp->num_planes = ctx->dst_fmt->mem_planes;
-
- pix_fmt_mp->plane_fmt[0].bytesperline = enc->dst_buf_size;
- pix_fmt_mp->plane_fmt[0].sizeimage = enc->dst_buf_size;
- } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src g_fmt\n");
- /* This is run on capture (encoder src) */
- raw = &ctx->raw_buf;
-
- pix_fmt_mp->width = ctx->img_width;
- pix_fmt_mp->height = ctx->img_height;
- pix_fmt_mp->field = V4L2_FIELD_NONE;
- pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
- pix_fmt_mp->num_planes = ctx->src_fmt->mem_planes;
- for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
- pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
- pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
- }
- } else {
- mfc_err_dev("invalid buf type (%d)\n", f->type);
- return -EINVAL;
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_fmt *fmt;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
- fmt = __mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
- if (!fmt) {
- mfc_err_dev("Unsupported format for %s\n",
- V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void __mfc_enc_check_format(struct mfc_ctx *ctx)
-{
- switch (ctx->src_fmt->fourcc) {
- case V4L2_PIX_FMT_NV16M_S10B:
- case V4L2_PIX_FMT_NV61M_S10B:
- case V4L2_PIX_FMT_NV16M_P210:
- case V4L2_PIX_FMT_NV61M_P210:
- mfc_debug(2, "[FRAME][10BIT] is 422 and 10bit format\n");
- ctx->is_10bit = 1;
- ctx->is_422 = 1;
- break;
- case V4L2_PIX_FMT_NV16M:
- case V4L2_PIX_FMT_NV61M:
- mfc_debug(2, "[FRAME] is 422 format\n");
- ctx->is_10bit = 0;
- ctx->is_422 = 1;
- break;
- case V4L2_PIX_FMT_NV12M_S10B:
- case V4L2_PIX_FMT_NV12M_P010:
- case V4L2_PIX_FMT_NV21M_S10B:
- case V4L2_PIX_FMT_NV21M_P010:
- mfc_debug(2, "[FRAME][10BIT] is 10bit format\n");
- ctx->is_10bit = 1;
- ctx->is_422 = 0;
- break;
- default:
- ctx->is_10bit = 0;
- ctx->is_422 = 0;
- break;
- }
- mfc_debug(2, "[FRAME] 10bit: %d, 422: %d\n", ctx->is_10bit, ctx->is_422);
-}
-
-static int __mfc_enc_check_resolution(struct mfc_ctx *ctx)
-{
- int max_width = 0, max_height = 0, min_width = 0, min_height = 0, swap_check = 0;
-
- /* Check max resolution */
- switch (ctx->codec_mode) {
- case MFC_REG_CODEC_HEVC_ENC:
- if (ctx->is_422) {
- max_width = 65536;
- max_height = 8192;
- swap_check = 1;
- } else {
- max_width = 8192;
- max_height = 8192;
- }
- break;
- case MFC_REG_CODEC_BPG_ENC:
- max_width = 65536;
- max_height = 8192;
- swap_check = 1;
- break;
- case MFC_REG_CODEC_H264_ENC:
- case MFC_REG_CODEC_VP8_ENC:
- max_width = 8192;
- max_height = 8192;
- break;
- case MFC_REG_CODEC_VP9_ENC:
- max_width = 4096;
- max_height = 8192;
- break;
- case MFC_REG_CODEC_MPEG4_ENC:
- max_width = 2048;
- max_height = 2048;
- break;
- case MFC_REG_CODEC_H263_ENC:
- max_width = 2048;
- max_height = 1152;
- break;
- default:
- mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
- return -EINVAL;
- }
-
- if (swap_check) {
- if (!((ctx->crop_width < max_width && ctx->crop_height < max_height) ||
- (ctx->crop_width < max_height && ctx->crop_height < max_width))) {
- mfc_err_ctx("Resolution is too big(%dx%d > %dxi%d or %dx%d\n",
- ctx->crop_width, ctx->crop_height, max_width, max_height,
- max_height, max_width);
- return -EINVAL;
- }
- } else {
- if (ctx->crop_width > max_width || ctx->crop_height > max_height) {
- mfc_err_ctx("Resolution is too big(%dx%d > %dx%d)\n",
- ctx->crop_width, ctx->crop_height, max_width, max_height);
- return -EINVAL;
- }
- }
-
- /* Check min resolution */
- switch (ctx->codec_mode) {
- case MFC_REG_CODEC_HEVC_ENC:
- case MFC_REG_CODEC_BPG_ENC:
- case MFC_REG_CODEC_VP9_ENC:
- min_width = 64;
- min_height = 64;
- break;
- case MFC_REG_CODEC_H264_ENC:
- case MFC_REG_CODEC_VP8_ENC:
- case MFC_REG_CODEC_MPEG4_ENC:
- case MFC_REG_CODEC_H263_ENC:
- min_width = 32;
- min_height = 32;
- break;
- default:
- mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
- return -EINVAL;
- }
-
- if (ctx->crop_width < min_width || ctx->crop_height < min_height) {
- mfc_err_ctx("Resolution is too small(%dx%d < %dx%d)\n",
- ctx->crop_width, ctx->crop_height, min_width, min_height);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mfc_dev *dev = video_drvdata(file);
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct mfc_enc *enc = ctx->enc_priv;
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
- int ret = 0;
-
- mfc_debug_enter();
-
- if (ctx->vq_dst.streaming) {
- mfc_err_ctx("dst queue busy\n");
- return -EBUSY;
- }
-
- ctx->dst_fmt = __mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
- if (!ctx->dst_fmt) {
- mfc_err_ctx("Unsupported format for destination\n");
- return -EINVAL;
- }
-
- ctx->codec_mode = ctx->dst_fmt->codec_mode;
- mfc_info_ctx("[STREAM] Enc dst codec(%d) : %s\n",
- ctx->codec_mode, ctx->dst_fmt->name);
-
- if (__mfc_enc_check_resolution(ctx)) {
- mfc_err_ctx("Unsupported resolution\n");
- return -EINVAL;
- }
-
- if (ctx->otf_handle) {
- if (ctx->dst_fmt->fourcc != V4L2_PIX_FMT_H264 &&
- ctx->dst_fmt->fourcc != V4L2_PIX_FMT_HEVC) {
- mfc_err_ctx("[OTF] only H.264 and HEVC is supported\n");
- return -EINVAL;
- }
- if (mfc_otf_init(ctx)) {
- mfc_err_ctx("[OTF] otf_init failed\n");
- mfc_otf_destroy(ctx);
- return -EINVAL;
- }
- }
-
- enc->dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
- pix_fmt_mp->plane_fmt[0].bytesperline = 0;
-
- ret = mfc_alloc_instance_context(ctx);
- if (ret) {
- mfc_err_ctx("Failed to allocate enc instance[%d] buffers\n",
- ctx->num);
- return -ENOMEM;
- }
-
- mfc_change_state(ctx, MFCINST_INIT);
-
- ctx->capture_state = QUEUE_FREE;
-
- ret = mfc_alloc_enc_roi_buffer(ctx);
- if (ret) {
- mfc_err_ctx("[ROI] Failed to allocate ROI buffers\n");
- mfc_release_instance_context(ctx);
- return -ENOMEM;
- }
-
- MFC_TRACE_CTX_HWLOCK("**ENC s_fmt\n");
-
- ret = mfc_get_hwlock_ctx(ctx);
- if (ret < 0) {
- mfc_err_dev("Failed to get hwlock\n");
- mfc_release_instance_context(ctx);
- mfc_release_enc_roi_buffer(ctx);
- return -EBUSY;
- }
-
- mfc_set_bit(ctx->num, &dev->work_bits);
- ret = mfc_just_run(dev, ctx->num);
- if (ret) {
- mfc_err_ctx("Failed to run MFC\n");
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- mfc_release_instance_context(ctx);
- mfc_release_enc_roi_buffer(ctx);
- return -EIO;
- }
-
- if (mfc_wait_for_done_ctx(ctx,
- MFC_REG_R2H_CMD_OPEN_INSTANCE_RET)) {
- mfc_err_ctx("time out during open instance\n");
- mfc_release_hwlock_ctx(ctx);
- mfc_cleanup_work_bit_and_try_run(ctx);
- mfc_release_instance_context(ctx);
- mfc_release_enc_roi_buffer(ctx);
- return -EIO;
- }
- mfc_release_hwlock_ctx(ctx);
-
- mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
-
- if (mfc_enc_ctx_ready(ctx))
- mfc_set_bit(ctx->num, &dev->work_bits);
- if (ctx->otf_handle && mfc_otf_ctx_ready(ctx))
- mfc_set_bit(ctx->num, &dev->work_bits);
- if (mfc_is_work_to_do(dev))
- queue_work(dev->butler_wq, &dev->butler_work);
-
- mfc_debug_leave();
- return 0;
-}
-
-static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
- mfc_debug_enter();
-
- if (ctx->vq_src.streaming) {
- mfc_err_ctx("src queue busy\n");
- return -EBUSY;
- }
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip source s_fmt\n");
- return 0;
- }
-
- ctx->src_fmt = __mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
- if (!ctx->src_fmt) {
- mfc_err_ctx("Unsupported format for source\n");
- return -EINVAL;
- }
-
- if (ctx->src_fmt->mem_planes != pix_fmt_mp->num_planes) {
- mfc_err_ctx("[FRAME] enc src plane number is different (%d != %d)\n",
- ctx->src_fmt->mem_planes, pix_fmt_mp->num_planes);
- return -EINVAL;
- }
-
- ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
- ctx->img_width = pix_fmt_mp->width;
- ctx->img_height = pix_fmt_mp->height;
- ctx->buf_stride = pix_fmt_mp->plane_fmt[0].bytesperline;
-
- __mfc_enc_check_format(ctx);
-
- if (ctx->state == MFCINST_RUNNING) {
- mfc_change_state(ctx, MFCINST_GOT_INST);
- mfc_info_ctx("[DRC] Enc resolution is changed\n");
- }
-
- mfc_info_ctx("[FRAME] enc src pixelformat : %s\n", ctx->src_fmt->name);
- mfc_info_ctx("[FRAME] resolution w: %d, h: %d, stride: %d\n",
- pix_fmt_mp->width, pix_fmt_mp->height, ctx->buf_stride);
-
- /*
- * It should be keep till buffer size and stride was calculated.
- * And it can be changed to real encoding size, if user call the s_crop.
- */
- ctx->crop_width = ctx->img_width;
- ctx->crop_height = ctx->img_height;
- mfc_enc_calc_src_size(ctx);
-
- ctx->output_state = QUEUE_FREE;
-
- mfc_debug_leave();
- return 0;
-}
-
-static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-
- mfc_debug_enter();
-
- cr->c.left = ctx->crop_left;
- cr->c.top = ctx->crop_top;
- cr->c.width = ctx->crop_width;
- cr->c.height = ctx->crop_height;
-
- mfc_debug(2, "[FRAME] enc crop w: %d, h: %d, offset l: %d t: %d\n",
- ctx->crop_width, ctx->crop_height, ctx->crop_left, ctx->crop_top);
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-
- mfc_debug_enter();
-
- if (cr->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_err_ctx("not supported type (It can only in the source)\n");
- return -EINVAL;
- }
-
- if (cr->c.left < 0 || cr->c.top < 0) {
- mfc_err_ctx("[FRAME] crop position is negative\n");
- return -EINVAL;
- }
-
- if ((cr->c.height > ctx->img_height) || (cr->c.top > ctx->img_height) ||
- (cr->c.width > ctx->img_width) || (cr->c.left > ctx->img_width) ||
- (cr->c.left <= (ctx->img_width - cr->c.width)) ||
- (cr->c.top <= (ctx->img_height - cr->c.height))) {
- mfc_err_ctx("[FRAME] Out of crop range: (%d,%d,%d,%d) from %dx%d\n",
- cr->c.left, cr->c.top, cr->c.width, cr->c.height,
- ctx->img_width, ctx->img_height);
- return -EINVAL;
- }
-
- ctx->crop_top = cr->c.top;
- ctx->crop_left = cr->c.left;
- ctx->crop_height = cr->c.height;
- ctx->crop_width = cr->c.width;
-
- mfc_debug(3, "[FRAME] enc original: %dx%d, crop: %dx%d, offset l: %d t: %d\n",
- ctx->img_width, ctx->img_height,
- ctx->crop_width, ctx->crop_height,
- ctx->crop_left, ctx->crop_top);
-
- return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *reqbufs)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = 0;
-
- mfc_debug_enter();
-
- if (reqbufs->memory == V4L2_MEMORY_MMAP) {
- mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
- return -EINVAL;
- }
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip reqbufs\n");
- return 0;
- }
-
- if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "enc dst reqbuf(%d)\n", reqbufs->count);
- if (reqbufs->count == 0) {
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- ctx->capture_state = QUEUE_FREE;
- return ret;
- }
-
- if (ctx->capture_state != QUEUE_FREE) {
- mfc_err_ctx("invalid capture state: %d\n", ctx->capture_state);
- return -EINVAL;
- }
-
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- if (ret) {
- mfc_err_ctx("error in vb2_reqbufs() for E(D)\n");
- return ret;
- }
-
- ctx->capture_state = QUEUE_BUFS_REQUESTED;
- } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src reqbuf(%d)\n", reqbufs->count);
- if (reqbufs->count == 0) {
- ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
- ctx->output_state = QUEUE_FREE;
- return ret;
- }
-
- if (ctx->output_state != QUEUE_FREE) {
- mfc_err_ctx("invalid output state: %d\n", ctx->output_state);
- return -EINVAL;
- }
-
- ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
- if (ret) {
- mfc_err_ctx("error in vb2_reqbufs() for E(S)\n");
- return ret;
- }
-
- ctx->output_state = QUEUE_BUFS_REQUESTED;
- } else {
- mfc_err_ctx("invalid buf type (%d)\n", reqbufs->type);
- return -EINVAL;
- }
-
- mfc_debug_leave();
-
- return ret;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = 0;
-
- mfc_debug_enter();
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip source querybuf\n");
- return 0;
- }
-
- if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "enc dst querybuf, state: %d\n", ctx->state);
- ret = vb2_querybuf(&ctx->vq_dst, buf);
- if (ret != 0) {
- mfc_err_dev("enc dst: error in vb2_querybuf()\n");
- return ret;
- }
- } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src querybuf, state: %d\n", ctx->state);
- ret = vb2_querybuf(&ctx->vq_src, buf);
- if (ret != 0) {
- mfc_err_dev("enc src: error in vb2_querybuf()\n");
- return ret;
- }
- } else {
- mfc_err_dev("invalid buf type (%d)\n", buf->type);
- return -EINVAL;
- }
-
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Queue a buffer */
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int i, ret = -EINVAL;
-
- mfc_debug_enter();
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip qbuf\n");
- return 0;
- }
-
- if (ctx->state == MFCINST_ERROR) {
- mfc_err_ctx("Call on QBUF after unrecoverable error\n");
- return -EIO;
- }
-
- if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
- mfc_err_ctx("multiplanar but length is zero\n");
- return -EIO;
- }
-
- if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src buf[%d] Q\n", buf->index);
- for (i = 0; i < ctx->src_fmt->num_planes; i++) {
- if (!buf->m.planes[i].bytesused) {
- mfc_debug(2, "[FRAME] enc src[%d] size zero, "
- "changed to buf size %d\n",
- i, buf->m.planes[i].length);
- buf->m.planes[i].bytesused = buf->m.planes[i].length;
- } else {
- mfc_debug(2, "[FRAME] enc src[%d] size %d\n",
- i, buf->m.planes[i].bytesused);
- }
- }
- ret = vb2_qbuf(&ctx->vq_src, buf);
- } else {
- mfc_debug(4, "enc dst buf[%d] Q\n", buf->index);
- ret = vb2_qbuf(&ctx->vq_dst, buf);
- }
-
- mfc_debug_leave();
- return ret;
-}
-
-/* Dequeue a buffer */
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret;
-
- mfc_debug_enter();
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip dqbuf\n");
- return 0;
- }
-
- if (ctx->state == MFCINST_ERROR) {
- mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
- return -EIO;
- }
- if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src buf[%d] DQ\n", buf->index);
- ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
- } else {
- mfc_debug(4, "enc dst buf[%d] DQ\n", buf->index);
- ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
- }
- mfc_debug_leave();
- return ret;
-}
-
-/* Stream on */
-static int vidioc_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = -EINVAL;
-
- mfc_debug_enter();
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip streamon\n");
- return 0;
- }
-
- if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src streamon\n");
- ret = vb2_streamon(&ctx->vq_src, type);
-
- if (!ret) {
- mfc_qos_on(ctx);
- }
- } else {
- mfc_debug(4, "enc dst streamon\n");
- ret = vb2_streamon(&ctx->vq_dst, type);
- }
-
- mfc_debug(2, "src: %d, dst: %d, state = %d, dpb_count = %d\n",
- mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
- mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
- ctx->state, ctx->dpb_count);
- mfc_debug_leave();
- return ret;
-}
-
-/* Stream off, which equals to a pause */
-static int vidioc_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret;
-
- mfc_debug_enter();
-
- if (ctx->otf_handle) {
- mfc_info_ctx("[OTF] skip streamoff\n");
- return 0;
- }
-
- ret = -EINVAL;
- if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src streamoff\n");
- mfc_qos_reset_last_framerate(ctx);
-
- ret = vb2_streamoff(&ctx->vq_src, type);
- if (!ret)
- mfc_qos_off(ctx);
- } else {
- mfc_debug(4, "enc dst streamoff\n");
- ret = vb2_streamoff(&ctx->vq_dst, type);
- }
-
- mfc_debug_leave();
-
- return ret;
-}
-
-/* Query a ctrl */
-static int vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *qc)
-{
- struct v4l2_queryctrl *c;
-
- c = __mfc_enc_get_ctrl(qc->id);
- if (!c) {
- mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
- return -EINVAL;
- }
-
- *qc = *c;
- return 0;
-}
-
-static int __mfc_enc_ext_info(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- int val = 0;
-
- val |= ENC_SET_SPARE_SIZE;
- val |= ENC_SET_TEMP_SVC_CH;
-
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
- val |= ENC_SET_SKYPE_FLAG;
-
- val |= ENC_SET_ROI_CONTROL;
- val |= ENC_SET_QP_BOUND_PB;
- val |= ENC_SET_FIXED_SLICE;
- val |= ENC_SET_PVC_MODE;
- val |= ENC_SET_RATIO_OF_INTRA;
-
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc))
- val |= ENC_SET_COLOR_ASPECT;
-
- val |= ENC_SET_HP_BITRATE_CONTROL;
-
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_enc))
- val |= ENC_SET_STATIC_INFO;
-
- mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
-
- return val;
-}
-
-static int __mfc_enc_get_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_ctx_ctrl *ctx_ctrl;
- int ret = 0;
- int found = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_CACHEABLE:
- mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_STREAM_SIZE:
- ctrl->value = enc->dst_buf_size;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE:
- ctrl->value = enc->frame_type;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
- ctrl->value = MFCSTATE_PROCESSING;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
- case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
- case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
-
- if (ctx_ctrl->id == ctrl->id) {
- if (ctx_ctrl->has_new) {
- ctx_ctrl->has_new = 0;
- ctrl->value = ctx_ctrl->val;
- } else {
- mfc_debug(5, "[CTRLS] Control value "\
- "is not up to date: "\
- "0x%08x\n", ctrl->id);
- return -EINVAL;
- }
-
- found = 1;
- break;
- }
- }
-
- if (!found) {
- mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
- return -EINVAL;
- }
- break;
- case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
- ctrl->value = dev->pdata->ip_ver;
- break;
- case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
- ctrl->value = MFC_DRIVER_INFO;
- break;
- case V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE:
- ctrl->value = MFC_LINEAR_BUF_SIZE;
- break;
- case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
- ctrl->value = ctx->qos_ratio;
- break;
- case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
- ctrl->value = __mfc_enc_ext_info(ctx);
- break;
- case V4L2_CID_MPEG_VIDEO_BPG_HEADER_SIZE:
- ctrl->value = enc->header_size;
- break;
- default:
- mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
- ret = -EINVAL;
- break;
- }
-
- mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
- return ret;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = 0;
-
- mfc_debug_enter();
- ret = __mfc_enc_get_ctrl_val(ctx, ctrl);
- mfc_debug_leave();
-
- return ret;
-}
-
-static inline int __mfc_enc_h264_level(enum v4l2_mpeg_video_h264_level lvl)
-{
- static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_5_1 + 1] = {
- /* V4L2_MPEG_VIDEO_H264_LEVEL_1_0 */ 10,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_1B */ 9,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_1_1 */ 11,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_1_2 */ 12,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_1_3 */ 13,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_2_0 */ 20,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_2_1 */ 21,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_2_2 */ 22,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_3_0 */ 30,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_3_1 */ 31,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_3_2 */ 32,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_4_0 */ 40,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_4_1 */ 41,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_4_2 */ 42,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_5_0 */ 50,
- /* V4L2_MPEG_VIDEO_H264_LEVEL_5_1 */ 51,
- };
- return t[lvl];
-}
-
-static inline int __mfc_enc_mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
-{
- static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_6 + 1] = {
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 */ 0,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B, Simple */ 9,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 */ 1,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 */ 2,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 */ 3,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B, Advanced */ 7,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 */ 4,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 */ 5,
- /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_6, Simple */ 6,
- };
- return t[lvl];
-}
-
-static inline int __mfc_enc_vui_sar_idc(enum v4l2_mpeg_video_h264_vui_sar_idc sar)
-{
- static unsigned int t[V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED + 1] = {
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED */ 0,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1 */ 1,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11 */ 2,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11 */ 3,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11 */ 4,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33 */ 5,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11 */ 6,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11 */ 7,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11 */ 8,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33 */ 9,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11 */ 10,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11 */ 11,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33 */ 12,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99 */ 13,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3 */ 14,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2 */ 15,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 */ 16,
- /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED */ 255,
- };
- return t[sar];
-}
-
-static int __mfc_enc_set_param(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_enc_params *p = &enc->params;
- int ret = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
- p->gop_size = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
- p->slice_mode =
- (enum v4l2_mpeg_video_multi_slice_mode)ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
- p->slice_mb = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
- p->slice_bit = ctrl->value * 8;
- break;
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW:
- p->slice_mb_row = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
- p->intra_refresh_mb = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
- p->pad = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
- p->pad_luma = (ctrl->value >> 16) & 0xff;
- p->pad_cb = (ctrl->value >> 8) & 0xff;
- p->pad_cr = (ctrl->value >> 0) & 0xff;
- break;
- case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
- p->rc_frame = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE:
- p->rc_bitrate = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
- p->rc_reaction_coeff = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
- enc->force_frame_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
- p->vbv_buf_size = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
- p->seq_hdr_mode =
- (enum v4l2_mpeg_video_header_mode)(ctrl->value);
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
- p->frame_skip_mode =
- (enum v4l2_mpeg_mfc51_video_frame_skip_mode)
- (ctrl->value);
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
- p->fixed_target_bit = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_B_FRAMES:
- p->num_b_frame = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
- p->codec.h264.profile =
- __mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
- break;
- case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
- p->codec.h264.level =
- __mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE:
- p->codec.h264.interlace = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
- p->codec.h264.loop_filter_mode =
- (enum v4l2_mpeg_video_h264_loop_filter_mode)(ctrl->value);
- break;
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
- p->codec.h264.loop_filter_alpha = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
- p->codec.h264.loop_filter_beta = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
- p->codec.h264.entropy_mode =
- (enum v4l2_mpeg_video_h264_entropy_mode)(ctrl->value);
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
- p->num_refs_for_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
- p->codec.h264._8x8_transform = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
- p->rc_mb = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE:
- p->rc_framerate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
- p->codec.h264.rc_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
- p->codec.h264.rc_min_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
- p->codec.h264.rc_max_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
- p->codec.h264.rc_min_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
- p->codec.h264.rc_max_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
- p->codec.h264.rc_min_qp_b = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
- p->codec.h264.rc_max_qp_b = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
- p->codec.h264.rc_mb_dark = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
- p->codec.h264.rc_mb_smooth = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
- p->codec.h264.rc_mb_static = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
- p->codec.h264.rc_mb_activity = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
- p->codec.h264.rc_p_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
- p->codec.h264.rc_b_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
- p->codec.h264.ar_vui = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
- p->codec.h264.ar_vui_idc =
- __mfc_enc_vui_sar_idc((enum v4l2_mpeg_video_h264_vui_sar_idc)(ctrl->value));
- break;
- case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
- p->codec.h264.ext_sar_width = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
- p->codec.h264.ext_sar_height = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
- p->codec.h264.open_gop = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
- p->codec.h264.open_gop_size = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:
- p->codec.h264.hier_qp_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
- p->codec.h264.hier_qp_type =
- (enum v4l2_mpeg_video_h264_hierarchical_coding_type)(ctrl->value);
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
- p->codec.h264.num_hier_layer = ctrl->value & 0x7;
- p->codec.h264.hier_ref_type = (ctrl->value >> 16) & 0x1;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
- p->codec.h264.hier_qp_layer[(ctrl->value >> 16) & 0x7]
- = ctrl->value & 0xFF;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0:
- p->codec.h264.hier_bit_layer[0] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1:
- p->codec.h264.hier_bit_layer[1] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2:
- p->codec.h264.hier_bit_layer[2] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3:
- p->codec.h264.hier_bit_layer[3] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4:
- p->codec.h264.hier_bit_layer[4] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5:
- p->codec.h264.hier_bit_layer[5] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6:
- p->codec.h264.hier_bit_layer[6] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
- p->codec.h264.sei_gen_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:
- p->codec.h264.sei_fp_curr_frame_0 = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
- p->codec.h264.sei_fp_arrangement_type = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_FMO:
- p->codec.h264.fmo_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
- switch ((enum v4l2_mpeg_video_h264_fmo_map_type)(ctrl->value)) {
- case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
- case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
- case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
- case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
- p->codec.h264.fmo_slice_map_type = ctrl->value;
- break;
- default:
- ret = -EINVAL;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:
- p->codec.h264.fmo_slice_num_grp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:
- p->codec.h264.fmo_run_length[(ctrl->value >> 30) & 0x3]
- = ctrl->value & 0x3FFFFFFF;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:
- p->codec.h264.fmo_sg_dir = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:
- p->codec.h264.fmo_sg_rate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_ASO:
- p->codec.h264.aso_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:
- p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
- &= ~(0xFF << (((ctrl->value >> 16) & 0x3) << 3));
- p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
- |= (ctrl->value & 0xFF) << \
- (((ctrl->value >> 16) & 0x3) << 3);
- break;
- case V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR:
- p->codec.h264.prepend_sps_pps_to_idr = ctrl->value ? 1 : 0;
- break;
- case V4L2_CID_MPEG_MFC_H264_ENABLE_LTR:
- p->codec.h264.enable_ltr = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR:
- p->codec.h264.num_of_ltr = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
- p->codec.h264.base_priority = ctrl->value;
- p->codec.h264.set_priority = 1;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
- switch ((enum v4l2_mpeg_video_mpeg4_profile)(ctrl->value)) {
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
- p->codec.mpeg4.profile =
- MFC_REG_E_PROFILE_MPEG4_SIMPLE;
- break;
- case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
- p->codec.mpeg4.profile =
- MFC_REG_E_PROFILE_MPEG4_ADVANCED_SIMPLE;
- break;
- default:
- ret = -EINVAL;
- }
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
- p->codec.mpeg4.level =
- __mfc_enc_mpeg4_level((enum v4l2_mpeg_video_mpeg4_level)(ctrl->value));
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
- p->codec.mpeg4.rc_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
- p->codec.mpeg4.rc_min_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
- p->codec.mpeg4.rc_max_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
- p->codec.mpeg4.rc_min_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
- p->codec.mpeg4.rc_max_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
- p->codec.mpeg4.rc_min_qp_b = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
- p->codec.mpeg4.rc_max_qp_b = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
- p->codec.mpeg4.quarter_pixel = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
- p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
- p->codec.mpeg4.rc_b_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES:
- p->codec.mpeg4.vop_time_res = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA:
- p->codec.mpeg4.vop_frm_delta = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE:
- p->rc_framerate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
- p->codec.mpeg4.rc_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
- p->codec.mpeg4.rc_min_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
- p->codec.mpeg4.rc_max_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
- p->codec.mpeg4.rc_min_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
- p->codec.mpeg4.rc_max_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
- p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION:
- p->codec.vp8.vp8_version = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE:
- p->rc_framerate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
- p->codec.vp8.rc_min_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
- p->codec.vp8.rc_max_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
- p->codec.vp8.rc_min_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
- p->codec.vp8.rc_max_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP:
- p->codec.vp8.rc_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP:
- p->codec.vp8.rc_p_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS:
- p->codec.vp8.vp8_numberofpartitions = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL:
- p->codec.vp8.vp8_filterlevel = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS:
- p->codec.vp8.vp8_filtersharpness = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL:
- p->codec.vp8.vp8_goldenframesel = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD:
- p->codec.vp8.vp8_gfrefreshperiod = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE:
- p->codec.vp8.hier_qp_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0:
- p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
- = ctrl->value & 0xFF;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1:
- p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
- = ctrl->value & 0xFF;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2:
- p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
- = ctrl->value & 0xFF;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0:
- p->codec.vp8.hier_bit_layer[0] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1:
- p->codec.vp8.hier_bit_layer[1] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2:
- p->codec.vp8.hier_bit_layer[2] = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES:
- p->num_refs_for_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4:
- p->codec.vp8.intra_4x4mode_disable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER:
- p->codec.vp8.num_hier_layer = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_VERSION:
- p->codec.vp9.vp9_version = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE:
- p->rc_framerate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
- p->codec.vp9.rc_min_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
- p->codec.vp9.rc_max_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
- p->codec.vp9.rc_min_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
- p->codec.vp9.rc_max_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP:
- p->codec.vp9.rc_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP:
- p->codec.vp9.rc_p_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL:
- p->codec.vp9.vp9_goldenframesel = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD:
- p->codec.vp9.vp9_gfrefreshperiod = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE:
- p->codec.vp9.hier_qp_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP:
- p->codec.vp9.hier_qp_layer[(ctrl->value >> 16) & 0x3]
- = ctrl->value & 0xFF;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0:
- p->codec.vp9.hier_bit_layer[0] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1:
- p->codec.vp9.hier_bit_layer[1] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2:
- p->codec.vp9.hier_bit_layer[2] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES:
- p->num_refs_for_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER:
- p->codec.vp9.num_hier_layer = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH:
- p->codec.vp9.max_partition_depth = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT:
- p->codec.vp9.intra_pu_split_disable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER:
- p->ivf_header_disable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
- p->codec.vp9.profile = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
- p->codec.hevc.rc_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
- p->codec.hevc.rc_p_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
- p->codec.hevc.rc_b_frame_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE:
- p->rc_framerate = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
- p->codec.hevc.rc_min_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
- p->codec.hevc.rc_max_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
- p->codec.hevc.rc_min_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
- p->codec.hevc.rc_max_qp_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
- p->codec.hevc.rc_min_qp_b = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
- p->codec.hevc.rc_max_qp_b = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
- p->codec.hevc.level = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
- p->codec.hevc.profile = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK:
- p->codec.hevc.rc_lcu_dark = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH:
- p->codec.hevc.rc_lcu_smooth = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC:
- p->codec.hevc.rc_lcu_static = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY:
- p->codec.hevc.rc_lcu_activity = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG:
- p->codec.hevc.tier_flag = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH:
- p->codec.hevc.max_partition_depth = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES:
- p->num_refs_for_p = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE:
- p->codec.hevc.refreshtype = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE:
- p->codec.hevc.const_intra_period_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE:
- p->codec.hevc.lossless_cu_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE:
- p->codec.hevc.wavefront_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE:
- p->codec.hevc.loopfilter_disable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY:
- p->codec.hevc.loopfilter_across = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE:
- p->codec.hevc.enable_ltr = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE:
- p->codec.hevc.hier_qp_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE:
- p->codec.hevc.hier_qp_type =
- (enum v4l2_mpeg_video_hevc_hierarchical_coding_type)(ctrl->value);
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:
- p->codec.hevc.num_hier_layer = ctrl->value & 0x7;
- p->codec.hevc.hier_ref_type = (ctrl->value >> 16) & 0x1;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:
- p->codec.hevc.hier_qp_layer[(ctrl->value >> 16) & 0x7]
- = ctrl->value & 0xFF;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:
- p->codec.hevc.hier_bit_layer[0] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:
- p->codec.hevc.hier_bit_layer[1] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:
- p->codec.hevc.hier_bit_layer[2] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:
- p->codec.hevc.hier_bit_layer[3] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:
- p->codec.hevc.hier_bit_layer[4] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:
- p->codec.hevc.hier_bit_layer[5] = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:
- p->codec.hevc.hier_bit_layer[6] = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE:
- p->codec.hevc.general_pb_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE:
- p->codec.hevc.temporal_id_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG:
- p->codec.hevc.strong_intra_smooth = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT:
- p->codec.hevc.intra_pu_split_disable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION:
- p->codec.hevc.tmv_prediction_disable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
- p->codec.hevc.max_num_merge_mv = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE:
- p->codec.hevc.encoding_nostartcode_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD:
- p->codec.hevc.refreshperiod = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
- p->codec.hevc.lf_beta_offset_div2 = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
- p->codec.hevc.lf_tc_offset_div2 = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
- p->codec.hevc.size_of_length_field = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF:
- p->codec.hevc.user_ref = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF:
- p->codec.hevc.store_ref = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_ROI_ENABLE:
- p->roi_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE:
- p->codec.h264.vui_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR:
- p->codec.hevc.prepend_sps_pps_to_idr = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE:
- p->dynamic_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC_CONFIG_QP:
- p->config_qp = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE:
- /* It is valid for H.264, HEVC, VP8, VP9 */
- p->rc_pvc = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER:
- p->num_hier_max_layer = ctrl->value;
- break;
- case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING:
- break;
- case V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE:
- p->weighted_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BPG_THUMBNAIL_SIZE:
- /* It should be included when NAL_START */
- p->codec.bpg.thumb_size = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_BPG_EXIF_SIZE:
- /* It should be included when NAL_START */
- p->codec.bpg.exif_size = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
- p->ratio_intra = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
- p->check_color_range = 1;
- p->color_range = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
- p->colour_primaries = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
- p->transfer_characteristics = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
- p->matrix_coefficients = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL:
- p->hier_bitrate_ctrl = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE:
- p->static_info_enable = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
- p->max_pic_average_light = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
- p->max_content_light = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
- p->max_display_luminance = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
- p->min_display_luminance = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
- p->white_point = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
- p->display_primaries_0 = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
- p->display_primaries_1 = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
- p->display_primaries_2 = ctrl->value;
- break;
- default:
- mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int __mfc_enc_set_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_enc_params *p = &enc->params;
- struct mfc_ctx_ctrl *ctx_ctrl;
- int ret = 0;
- int found = 0;
- int index = 0;
-
- mfc_debug(5, "[CTRLS] id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
- switch (ctrl->id) {
- case V4L2_CID_CACHEABLE:
- mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
- break;
- case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
- ctx->qos_ratio = ctrl->value;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
- case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
- case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
- case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
- case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
- case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
- case V4L2_CID_MPEG_MFC_H264_USE_LTR:
- case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
- case V4L2_CID_MPEG_MFC_CONFIG_QP:
- case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
- case V4L2_CID_MPEG_VIDEO_YSUM:
- case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
- continue;
-
- if (ctx_ctrl->id == ctrl->id) {
- ctx_ctrl->has_new = 1;
- ctx_ctrl->val = ctrl->value;
- if (ctx_ctrl->id == \
- V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH) {
- ctx_ctrl->val &= ~(0xFFFF << 16);
- ctx_ctrl->val |= ctx_ctrl->val << 16;
- ctx_ctrl->val &= ~(0xFFFF);
- ctx_ctrl->val |= p->rc_frame_delta & 0xFFFF;
- }
- if (((ctx_ctrl->id == \
- V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH) ||
- (ctx_ctrl->id == \
- V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH) ||
- (ctx_ctrl->id == \
- V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH) ||
- (ctx_ctrl->id == \
- V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH)) &&
- (enc->sh_handle_svc.fd == -1)) {
- enc->sh_handle_svc.fd = ctrl->value;
- if (mfc_mem_get_user_shared_handle(ctx,
- &enc->sh_handle_svc))
- return -EINVAL;
- else
- mfc_debug(2, "[MEMINFO][HIERARCHICAL] shared handle fd: %d, vaddr: 0x%p\n",
- enc->sh_handle_svc.fd,
- enc->sh_handle_svc.vaddr);
- }
- if (ctx_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH &&
- p->i_frm_ctrl_mode) {
- ctx_ctrl->val = ctx_ctrl->val * (p->num_b_frame + 1);
- if (ctx_ctrl->val >= 0x3FFFFFFF) {
- mfc_info_ctx("I frame interval is bigger than max: %d\n",
- ctx_ctrl->val);
- ctx_ctrl->val = 0x3FFFFFFF;
- }
- }
- if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL)
- ctx_ctrl->val = __mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
- if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE)
- ctx_ctrl->val = __mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
- if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
- if (enc->sh_handle_roi.fd == -1) {
- enc->sh_handle_roi.fd = ctrl->value;
- if (mfc_mem_get_user_shared_handle(ctx,
- &enc->sh_handle_roi))
- return -EINVAL;
- else
- mfc_debug(2, "[MEMINFO][ROI] shared handle fd: %d, vaddr: 0x%p\n",
- enc->sh_handle_roi.fd,
- enc->sh_handle_roi.vaddr);
- }
- index = enc->roi_index;
- memcpy(&enc->roi_info[index],
- enc->sh_handle_roi.vaddr,
- sizeof(struct mfc_enc_roi_info));
- if (copy_from_user(enc->roi_buf[index].vaddr,
- enc->roi_info[index].addr,
- enc->roi_info[index].size))
- return -EFAULT;
- }
-
- found = 1;
- break;
- }
- }
-
- if (!found) {
- mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
- return -EINVAL;
- }
- break;
- default:
- ret = __mfc_enc_set_param(ctx, ctrl);
- break;
- }
-
- return ret;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctrl)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- int ret = 0;
-
- mfc_debug_enter();
-
- ret = __mfc_enc_check_ctrl_val(ctx, ctrl);
- if (ret != 0)
- return ret;
-
- ret = __mfc_enc_set_ctrl_val(ctx, ctrl);
-
- mfc_debug_leave();
-
- return ret;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct v4l2_ext_control *ext_ctrl;
- struct v4l2_control ctrl;
- int i;
- int ret = 0;
-
- if (f->which != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- for (i = 0; i < f->count; i++) {
- ext_ctrl = (f->controls + i);
-
- ctrl.id = ext_ctrl->id;
-
- ret = __mfc_enc_get_ctrl_val(ctx, &ctrl);
- if (ret == 0) {
- ext_ctrl->value = ctrl.value;
- } else {
- f->error_idx = i;
- break;
- }
-
- mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
- i, ext_ctrl->id, ext_ctrl->value);
- }
-
- return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct v4l2_ext_control *ext_ctrl;
- struct v4l2_control ctrl;
- int i;
- int ret = 0;
-
- if (f->which != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- for (i = 0; i < f->count; i++) {
- ext_ctrl = (f->controls + i);
-
- ctrl.id = ext_ctrl->id;
- ctrl.value = ext_ctrl->value;
-
- ret = __mfc_enc_check_ctrl_val(ctx, &ctrl);
- if (ret != 0) {
- f->error_idx = i;
- break;
- }
-
- ret = __mfc_enc_set_param(ctx, &ctrl);
- if (ret != 0) {
- f->error_idx = i;
- break;
- }
-
- mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
- i, ext_ctrl->id, ext_ctrl->value);
- }
-
- return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *f)
-{
- struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
- struct v4l2_ext_control *ext_ctrl;
- struct v4l2_control ctrl;
- int i;
- int ret = 0;
-
- if (f->which != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- for (i = 0; i < f->count; i++) {
- ext_ctrl = (f->controls + i);
-
- ctrl.id = ext_ctrl->id;
- ctrl.value = ext_ctrl->value;
-
- ret = __mfc_enc_check_ctrl_val(ctx, &ctrl);
- if (ret != 0) {
- f->error_idx = i;
- break;
- }
-
- mfc_debug(2, "[%d] id: 0x%08x, value: %d\n", i, ext_ctrl->id, ext_ctrl->value);
- }
-
- return ret;
-}
-
-static const struct v4l2_ioctl_ops mfc_enc_ioctl_ops = {
- .vidioc_querycap = vidioc_querycap,
- .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
- .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
- .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
- .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
- .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
- .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
- .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane,
- .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out_mplane,
- .vidioc_g_crop = vidioc_g_crop,
- .vidioc_s_crop = vidioc_s_crop,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
- .vidioc_queryctrl = vidioc_queryctrl,
- .vidioc_g_ctrl = vidioc_g_ctrl,
- .vidioc_s_ctrl = vidioc_s_ctrl,
- .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
- .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
- .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
-};
-
-const struct v4l2_ioctl_ops *mfc_get_enc_v4l2_ioctl_ops(void)
-{
- return &mfc_enc_ioctl_ops;
-}
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_enc.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MFC_ENC_H
-#define __MFC_ENC_H __FILE__
-
-#include "mfc_common.h"
-
-const struct v4l2_ioctl_ops *mfc_get_enc_v4l2_ioctl_ops(void);
-
-#endif /* __MFC_ENC_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_enc_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_common.h"
+
+#include "mfc_reg_api.h"
+
+static int __mfc_enc_ctrl_read_cst(struct mfc_ctx *ctx,
+ struct mfc_buf_ctrl *buf_ctrl)
+{
+ int ret;
+ struct mfc_enc *enc = ctx->enc_priv;
+
+ switch (buf_ctrl->id) {
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+ ret = !enc->in_slice;
+ break;
+ default:
+ mfc_err_ctx("not support custom per-buffer control\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static struct mfc_ctrl_cfg mfc_ctrl_list[] = {
+ { /* set frame tag */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_PICTURE_TAG,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* get frame tag */
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RET_PICTURE_TAG,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* encoded y physical addr */
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* encoded c physical addr */
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_ENCODED_SOURCE_SECOND_ADDR,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* I, not coded frame insertion */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_FRAME_INSERTION,
+ .mask = 0x3,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* I period change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_GOP_CONFIG,
+ .mask = 0xFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 0,
+ },
+ { /* frame rate change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_FRAME_RATE,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 1,
+ },
+ { /* bit rate change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_BIT_RATE,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 2,
+ },
+ { /* frame status (in slice or not) */
+ .type = MFC_CTRL_TYPE_GET_DST,
+ .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS,
+ .is_volatile = 0,
+ .mode = MFC_CTRL_MODE_CST,
+ .addr = 0,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ .read_cst = __mfc_enc_ctrl_read_cst,
+ .write_cst = NULL,
+ },
+ { /* H.264 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.263 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.263 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP8 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP8 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP9 I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP9 I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC I frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC I frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.263 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.263 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP8 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP8 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP9 P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* VP9 P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC P frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC P frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 B frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 B frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 B frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* MPEG4 B frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC B frame QP Max change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* HEVC B frame QP Min change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_QP_BOUND_PB,
+ .mask = 0xFF,
+ .shft = 16,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 4,
+ },
+ { /* H.264 Dynamic Temporal Layer & bitrate change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 10,
+ },
+ { /* HEVC Dynamic Temporal Layer & bitrate change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 10,
+ },
+ { /* VP8 Dynamic Temporal Layer change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 10,
+ },
+ { /* VP9 Dynamic Temporal Layer change */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 10,
+ },
+ { /* set level */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_PICTURE_PROFILE,
+ .mask = 0x000000FF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 5,
+ },
+ { /* set profile */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_PICTURE_PROFILE,
+ .mask = 0x0000000F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 5,
+ },
+ { /* set store LTR */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_H264_NAL_CONTROL,
+ .mask = 0x00000003,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* set use LTR */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_H264_NAL_CONTROL,
+ .mask = 0x00000003,
+ .shft = 2,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* set base layer priority */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_H264_HD_SVC_EXTENSION_0,
+ .mask = 0x0000003F,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 12,
+ },
+ { /* set QP per each frame */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_FIXED_PICTURE_QP,
+ .mask = 0x000000FF,
+ .shft = 24,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* Region-Of-Interest control */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_ROI_CONTROL,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_ROI_CTRL,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_addr = 0,
+ .flag_shft = 0,
+ },
+ { /* set YSUM for weighted prediction */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_YSUM,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_WEIGHT_FOR_WEIGHTED_PREDICTION,
+ .mask = 0xFFFFFFFF,
+ .shft = 0,
+ .flag_mode = MFC_CTRL_MODE_NONE,
+ .flag_mode = 0,
+ .flag_shft = 0,
+ },
+ { /* set base layer priority */
+ .type = MFC_CTRL_TYPE_SET,
+ .id = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA,
+ .is_volatile = 1,
+ .mode = MFC_CTRL_MODE_SFR,
+ .addr = MFC_REG_E_RC_MODE,
+ .mask = 0x000000FF,
+ .shft = 8,
+ .flag_mode = MFC_CTRL_MODE_SFR,
+ .flag_addr = MFC_REG_E_PARAM_CHANGE,
+ .flag_shft = 13,
+ }
+};
+
+#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
+
+static int mfc_enc_cleanup_ctx_ctrls(struct mfc_ctx *ctx)
+{
+ struct mfc_ctx_ctrl *ctx_ctrl;
+
+ while (!list_empty(&ctx->ctrls)) {
+ ctx_ctrl = list_entry((&ctx->ctrls)->next,
+ struct mfc_ctx_ctrl, list);
+ list_del(&ctx_ctrl->list);
+ kfree(ctx_ctrl);
+ }
+
+ INIT_LIST_HEAD(&ctx->ctrls);
+
+ return 0;
+}
+
+static int mfc_enc_get_buf_update_val(struct mfc_ctx *ctx,
+ struct list_head *head, unsigned int id, int value)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (buf_ctrl->id == id) {
+ buf_ctrl->val = value;
+ mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int mfc_enc_init_ctx_ctrls(struct mfc_ctx *ctx)
+{
+ unsigned long i;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+
+ INIT_LIST_HEAD(&ctx->ctrls);
+
+ for (i = 0; i < NUM_CTRL_CFGS; i++) {
+ ctx_ctrl = kzalloc(sizeof(struct mfc_ctx_ctrl), GFP_KERNEL);
+ if (ctx_ctrl == NULL) {
+ mfc_err_dev("Failed to allocate context control "\
+ "id: 0x%08x, type: %d\n",
+ mfc_ctrl_list[i].id,
+ mfc_ctrl_list[i].type);
+
+ mfc_enc_cleanup_ctx_ctrls(ctx);
+
+ return -ENOMEM;
+ }
+
+ ctx_ctrl->type = mfc_ctrl_list[i].type;
+ ctx_ctrl->id = mfc_ctrl_list[i].id;
+ ctx_ctrl->has_new = 0;
+ ctx_ctrl->val = 0;
+
+ list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
+ }
+
+ return 0;
+}
+
+static void mfc_enc_reset_buf_ctrls(struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ buf_ctrl->has_new = 0;
+ buf_ctrl->val = 0;
+ buf_ctrl->old_val = 0;
+ buf_ctrl->updated = 0;
+ }
+}
+
+static void __mfc_enc_remove_buf_ctrls(struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ while (!list_empty(head)) {
+ buf_ctrl = list_entry(head->next,
+ struct mfc_buf_ctrl, list);
+ list_del(&buf_ctrl->list);
+ kfree(buf_ctrl);
+ }
+
+ INIT_LIST_HEAD(head);
+}
+
+static int mfc_enc_init_buf_ctrls(struct mfc_ctx *ctx,
+ enum mfc_ctrl_type type, unsigned int index)
+{
+ unsigned long i;
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct list_head *head;
+
+ if (index >= MFC_MAX_BUFFERS) {
+ mfc_err_dev("Per-buffer control index is out of range\n");
+ return -EINVAL;
+ }
+
+ if (type & MFC_CTRL_TYPE_SRC) {
+ if (test_bit(index, &ctx->src_ctrls_avail)) {
+ mfc_enc_reset_buf_ctrls(&ctx->src_ctrls[index]);
+
+ return 0;
+ }
+
+ head = &ctx->src_ctrls[index];
+ } else if (type & MFC_CTRL_TYPE_DST) {
+ if (test_bit(index, &ctx->dst_ctrls_avail)) {
+ mfc_enc_reset_buf_ctrls(&ctx->dst_ctrls[index]);
+
+ return 0;
+ }
+
+ head = &ctx->dst_ctrls[index];
+ } else {
+ mfc_err_dev("Control type mismatch. type : %d\n", type);
+ return -EINVAL;
+ }
+
+ INIT_LIST_HEAD(head);
+
+ for (i = 0; i < NUM_CTRL_CFGS; i++) {
+ if (!(type & mfc_ctrl_list[i].type))
+ continue;
+
+ buf_ctrl = kzalloc(sizeof(struct mfc_buf_ctrl), GFP_KERNEL);
+ if (buf_ctrl == NULL) {
+ mfc_err_dev("Failed to allocate buffer control "\
+ "id: 0x%08x, type: %d\n",
+ mfc_ctrl_list[i].id,
+ mfc_ctrl_list[i].type);
+
+ __mfc_enc_remove_buf_ctrls(head);
+
+ return -ENOMEM;
+ }
+
+ buf_ctrl->type = mfc_ctrl_list[i].type;
+ buf_ctrl->id = mfc_ctrl_list[i].id;
+ buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
+ buf_ctrl->mode = mfc_ctrl_list[i].mode;
+ buf_ctrl->addr = mfc_ctrl_list[i].addr;
+ buf_ctrl->mask = mfc_ctrl_list[i].mask;
+ buf_ctrl->shft = mfc_ctrl_list[i].shft;
+ buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
+ buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
+ buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
+ if (buf_ctrl->mode == MFC_CTRL_MODE_CST) {
+ buf_ctrl->read_cst = mfc_ctrl_list[i].read_cst;
+ buf_ctrl->write_cst = mfc_ctrl_list[i].write_cst;
+ }
+
+ list_add_tail(&buf_ctrl->list, head);
+ }
+
+ mfc_enc_reset_buf_ctrls(head);
+
+ if (type & MFC_CTRL_TYPE_SRC)
+ set_bit(index, &ctx->src_ctrls_avail);
+ else
+ set_bit(index, &ctx->dst_ctrls_avail);
+
+ return 0;
+}
+
+static int mfc_enc_cleanup_buf_ctrls(struct mfc_ctx *ctx,
+ enum mfc_ctrl_type type, unsigned int index)
+{
+ struct list_head *head;
+
+ if (index >= MFC_MAX_BUFFERS) {
+ mfc_err_dev("Per-buffer control index is out of range\n");
+ return -EINVAL;
+ }
+
+ if (type & MFC_CTRL_TYPE_SRC) {
+ if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
+ return 0;
+ }
+
+ head = &ctx->src_ctrls[index];
+ } else if (type & MFC_CTRL_TYPE_DST) {
+ if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
+ return 0;
+ }
+
+ head = &ctx->dst_ctrls[index];
+ } else {
+ mfc_err_dev("Control type mismatch. type : %d\n", type);
+ return -EINVAL;
+ }
+
+ __mfc_enc_remove_buf_ctrls(head);
+
+ return 0;
+}
+
+static int mfc_enc_to_buf_ctrls(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_enc *enc = ctx->enc_priv;
+ int index = 0;
+ unsigned int reg = 0;
+
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
+ continue;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
+ continue;
+
+ if (buf_ctrl->id == ctx_ctrl->id) {
+ buf_ctrl->has_new = 1;
+ buf_ctrl->val = ctx_ctrl->val;
+ if (buf_ctrl->is_volatile)
+ buf_ctrl->updated = 0;
+
+ ctx_ctrl->has_new = 0;
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+ index = enc->roi_index;
+ if (enc->roi_info[index].enable) {
+ enc->roi_index =
+ (index + 1) % MFC_MAX_EXTRA_BUF;
+ reg |= enc->roi_info[index].enable;
+ reg &= ~(0xFF << 8);
+ reg |= (enc->roi_info[index].lower_qp << 8);
+ reg &= ~(0xFFFF << 16);
+ reg |= (enc->roi_info[index].upper_qp << 16);
+ mfc_debug(3, "[ROI] buffer[%d] en %d, "\
+ "QP lower %d upper %d reg %#x\n",
+ index, enc->roi_info[index].enable,
+ enc->roi_info[index].lower_qp,
+ enc->roi_info[index].upper_qp,
+ reg);
+ } else {
+ mfc_debug(3, "[ROI] buffer[%d] is not enabled\n", index);
+ }
+ buf_ctrl->val = reg;
+ buf_ctrl->old_val2 = index;
+ }
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mfc_enc_to_ctx_ctrls(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
+ continue;
+
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+
+ if (ctx_ctrl->id == buf_ctrl->id) {
+ if (ctx_ctrl->has_new)
+ mfc_debug(8,
+ "Overwrite context control "\
+ "value id: 0x%08x, val: %d\n",
+ ctx_ctrl->id, ctx_ctrl->val);
+
+ ctx_ctrl->has_new = 1;
+ ctx_ctrl->val = buf_ctrl->val;
+
+ buf_ctrl->has_new = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void __mfc_enc_set_buf_ctrls_temporal_svc(struct mfc_ctx *ctx,
+ struct mfc_buf_ctrl *buf_ctrl)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ unsigned int value = 0, value2 = 0;
+ struct temporal_layer_info temporal_LC;
+ unsigned int i;
+ struct mfc_enc_params *p = &enc->params;
+
+ if (buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
+ memcpy(&temporal_LC,
+ enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
+
+ if(((temporal_LC.temporal_layer_count & 0x7) < 1) ||
+ ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
+ ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
+ /* clear NUM_T_LAYER_CHANGE */
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value &= ~(1 << 10);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ mfc_err_ctx("[HIERARCHICAL] layer count is invalid : %d\n",
+ temporal_LC.temporal_layer_count);
+ return;
+ }
+
+ if (IS_H264_ENC(ctx))
+ p->codec.h264.num_hier_layer = temporal_LC.temporal_layer_count & 0x7;
+
+ /* enable RC_BIT_RATE_CHANGE */
+ value = MFC_READL(buf_ctrl->flag_addr);
+ if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
+ /* set RC_BIT_RATE_CHANGE */
+ value |= (1 << 2);
+ else
+ /* clear RC_BIT_RATE_CHANGE */
+ value &= ~(1 << 2);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+
+ mfc_debug(3, "[HIERARCHICAL] layer count %d, E_PARAM_CHANGE %#x\n",
+ temporal_LC.temporal_layer_count & 0x7, value);
+
+ value = MFC_READL(MFC_REG_E_NUM_T_LAYER);
+ buf_ctrl->old_val2 = value;
+ value &= ~(0x7);
+ value |= (temporal_LC.temporal_layer_count & 0x7);
+ value &= ~(0x1 << 8);
+ value |= (p->hier_bitrate_ctrl & 0x1) << 8;
+ MFC_WRITEL(value, MFC_REG_E_NUM_T_LAYER);
+ mfc_debug(3, "[HIERARCHICAL] E_NUM_T_LAYER %#x\n", value);
+ for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+ mfc_debug(3, "[HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
+ i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
+ MFC_WRITEL(temporal_LC.temporal_layer_bitrate[i],
+ buf_ctrl->addr + i * 4);
+ }
+ /* priority change */
+ if (IS_H264_ENC(ctx)) {
+ value = 0;
+ value2 = 0;
+ for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
+ if (i <= 4)
+ value |= ((p->codec.h264.base_priority & 0x3F) + i)
+ << (6 * i);
+ else
+ value2 |= ((p->codec.h264.base_priority & 0x3F) + i)
+ << (6 * (i - 5));
+ }
+ MFC_WRITEL(value, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+ MFC_WRITEL(value2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
+ mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+ value, value2);
+
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value |= (1 << 12);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ mfc_debug(3, "[HIERARCHICAL] E_PARAM_CHANGE %#x\n", value);
+ }
+
+ }
+
+ /* temproral layer priority */
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+ value = MFC_READL(MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+ buf_ctrl->old_val |= value & 0x3FFFFFC0;
+ value &= ~(0x3FFFFFC0);
+ value2 = MFC_READL(MFC_REG_E_H264_HD_SVC_EXTENSION_1);
+ buf_ctrl->old_val2 = value2 & 0x0FFF;
+ value2 &= ~(0x0FFF);
+ for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
+ if (i <= 4)
+ value |= ((buf_ctrl->val & 0x3F) + i) << (6 * i);
+ else
+ value2 |= ((buf_ctrl->val & 0x3F) + i) << (6 * (i - 5));
+ }
+ MFC_WRITEL(value, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+ MFC_WRITEL(value2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
+ p->codec.h264.base_priority = buf_ctrl->val;
+ mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+ value, value2);
+ }
+}
+
+static void __mfc_enc_set_buf_ctrls_exception(struct mfc_ctx *ctx,
+ struct mfc_buf_ctrl *buf_ctrl)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_enc_params *p = &enc->params;
+ unsigned int value = 0;
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
+ enc->stored_tag = buf_ctrl->val;
+
+ /* temporal layer setting */
+ __mfc_enc_set_buf_ctrls_temporal_svc(ctx, buf_ctrl);
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+ value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
+ buf_ctrl->old_val2 = (value >> 8) & 0x7;
+ value &= ~(0x7 << 8);
+ value |= (buf_ctrl->val & 0x7) << 8;
+ MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+ value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
+ buf_ctrl->old_val2 = (value >> 11) & 0xF;
+ value &= ~(0xF << 11);
+ value |= (buf_ctrl->val & 0xF) << 11;
+ MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+ }
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
+ value = MFC_READL(MFC_REG_E_GOP_CONFIG2);
+ buf_ctrl->old_val |= (value << 16) & 0x3FFF0000;
+ value &= ~(0x3FFF);
+ value |= (buf_ctrl->val >> 16) & 0x3FFF;
+ MFC_WRITEL(value, MFC_REG_E_GOP_CONFIG2);
+ }
+
+ /* PROFILE & LEVEL have to be set up together */
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+ value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
+ buf_ctrl->old_val |= (value & 0x000F) << 8;
+ value &= ~(0x000F);
+ value |= p->codec.h264.profile & 0x000F;
+ MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+ p->codec.h264.level = buf_ctrl->val;
+ }
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+ value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
+ buf_ctrl->old_val |= value & 0xFF00;
+ value &= ~(0x00FF << 8);
+ value |= (p->codec.h264.level << 8) & 0xFF00;
+ MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+ p->codec.h264.profile = buf_ctrl->val;
+ }
+
+ /* per buffer QP setting change */
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_CONFIG_QP)
+ p->config_qp = buf_ctrl->val;
+
+ /* set the ROI buffer DVA */
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+ MFC_WRITEL(enc->roi_buf[buf_ctrl->old_val2].daddr,
+ MFC_REG_E_ROI_BUFFER_ADDR);
+ mfc_debug(3, "[ROI] buffer[%d] addr %#llx, QP val: %#x\n",
+ buf_ctrl->old_val2,
+ enc->roi_buf[buf_ctrl->old_val2].daddr,
+ buf_ctrl->val);
+ }
+}
+
+static int mfc_enc_set_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ unsigned int value = 0;
+ struct mfc_enc_params *p = &enc->params;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+ continue;
+
+ /* read old vlaue */
+ value = MFC_READL(buf_ctrl->addr);
+
+ /* save old value for recovery */
+ if (buf_ctrl->is_volatile)
+ buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+ /* write new value */
+ value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
+ MFC_WRITEL(value, buf_ctrl->addr);
+
+ /* set change flag bit */
+ if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value |= (1 << buf_ctrl->flag_shft);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ }
+
+ buf_ctrl->has_new = 0;
+ buf_ctrl->updated = 1;
+
+ __mfc_enc_set_buf_ctrls_exception(ctx, buf_ctrl);
+
+ mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
+ value = MFC_READL(MFC_REG_E_FIXED_PICTURE_QP);
+ value &= ~(0xFF000000);
+ value |= (p->config_qp & 0xFF) << 24;
+ MFC_WRITEL(value, MFC_REG_E_FIXED_PICTURE_QP);
+ mfc_debug(6, "[CTRLS] Dynamic QP changed %#x\n",
+ MFC_READL(MFC_REG_E_FIXED_PICTURE_QP));
+ }
+
+ return 0;
+}
+
+static int mfc_enc_get_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dev *dev = ctx->dev;
+ unsigned int value = 0;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+
+ if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
+ value = MFC_READL(buf_ctrl->addr);
+ else if (buf_ctrl->mode == MFC_CTRL_MODE_CST)
+ value = call_bop(buf_ctrl, read_cst, ctx, buf_ctrl);
+
+ value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+ buf_ctrl->val = value;
+ buf_ctrl->has_new = 1;
+
+ mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ return 0;
+}
+
+static int mfc_enc_set_buf_ctrls_val_nal_q_enc(struct mfc_ctx *ctx,
+ struct list_head *head, EncoderInputStr *pInStr)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct temporal_layer_info temporal_LC;
+ unsigned int i, param_change;
+ struct mfc_enc_params *p = &enc->params;
+
+ mfc_debug_enter();
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+ continue;
+ param_change = 0;
+ switch (buf_ctrl->id) {
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+ pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->PictureTag |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ enc->stored_tag = buf_ctrl->val;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+ pInStr->FrameInsertion &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->FrameInsertion |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
+ pInStr->GopConfig &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->GopConfig |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ pInStr->GopConfig2 &= ~(0x3FFF);
+ pInStr->GopConfig2 |= (buf_ctrl->val >> 16) & 0x3FFF;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
+ pInStr->RcFrameRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->RcFrameRate |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
+ pInStr->RcBitRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->RcBitRate |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
+ pInStr->RcQpBound &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->RcQpBound |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+ pInStr->RcQpBoundPb &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->RcQpBoundPb |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
+ memcpy(&temporal_LC,
+ enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
+
+ if (((temporal_LC.temporal_layer_count & 0x7) < 1) ||
+ ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
+ ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
+ /* claer NUM_T_LAYER_CHANGE */
+ mfc_err_ctx("[NALQ][HIERARCHICAL] layer count(%d) is invalid\n",
+ temporal_LC.temporal_layer_count);
+ return 0;
+ }
+
+ if (IS_H264_ENC(ctx))
+ p->codec.h264.num_hier_layer =
+ temporal_LC.temporal_layer_count & 0x7;
+
+ /* enable RC_BIT_RATE_CHANGE */
+ if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
+ pInStr->ParamChange |= (1 << 2);
+ else
+ pInStr->ParamChange &= ~(1 << 2);
+
+ /* enalbe NUM_T_LAYER_CHANGE */
+ if (temporal_LC.temporal_layer_count & 0x7)
+ pInStr->ParamChange |= (1 << 10);
+ else
+ pInStr->ParamChange &= ~(1 << 10);
+ mfc_debug(3, "[NALQ][HIERARCHICAL] layer count %d\n",
+ temporal_LC.temporal_layer_count & 0x7);
+
+ pInStr->NumTLayer &= ~(0x7);
+ pInStr->NumTLayer |= (temporal_LC.temporal_layer_count & 0x7);
+ pInStr->NumTLayer &= ~(0x1 << 8);
+ pInStr->NumTLayer |= (p->hier_bitrate_ctrl & 0x1) << 8;
+ for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+ mfc_debug(3, "[NALQ][HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
+ i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
+ pInStr->HierarchicalBitRateLayer[i] =
+ temporal_LC.temporal_layer_bitrate[i];
+ }
+
+ /* priority change */
+ if (IS_H264_ENC(ctx)) {
+ for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+ if (i <= 4)
+ pInStr->H264HDSvcExtension0 |=
+ ((p->codec.h264.base_priority & 0x3f) + i) << (6 * i);
+ else
+ pInStr->H264HDSvcExtension1 |=
+ ((p->codec.h264.base_priority & 0x3f) + i) << (6 * (i - 5));
+ }
+ mfc_debug(3, "[NALQ][HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+ pInStr->H264HDSvcExtension0, pInStr->H264HDSvcExtension1);
+
+ pInStr->ParamChange |= (1 << 12);
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+ pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->PictureProfile |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ pInStr->PictureProfile &= ~(0xf);
+ pInStr->PictureProfile |= p->codec.h264.profile & 0xf;
+ p->codec.h264.level = buf_ctrl->val;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->PictureProfile |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ pInStr->PictureProfile &= ~(0xff << 8);
+ pInStr->PictureProfile |= (p->codec.h264.level << 8) & 0xff00;
+ p->codec.h264.profile = buf_ctrl->val;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
+ pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->H264NalControl |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ pInStr->H264NalControl &= ~(0x7 << 8);
+ pInStr->H264NalControl |= (buf_ctrl->val & 0x7) << 8;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_USE_LTR:
+ pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->H264NalControl |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ pInStr->H264NalControl &= ~(0xF << 11);
+ pInStr->H264NalControl |= (buf_ctrl->val & 0xF) << 11;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+ for (i = 0; i < (p->codec.h264.num_hier_layer & 0x7); i++)
+ if (i <= 4)
+ pInStr->H264HDSvcExtension0 |=
+ ((buf_ctrl->val & 0x3f) + i) << (6 * i);
+ else
+ pInStr->H264HDSvcExtension1 |=
+ ((buf_ctrl->val & 0x3f) + i) << (6 * (i - 5));
+ p->codec.h264.base_priority = buf_ctrl->val;
+ param_change = 1;
+ break;
+ case V4L2_CID_MPEG_MFC_CONFIG_QP:
+ pInStr->FixedPictureQp &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->FixedPictureQp |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ p->config_qp = buf_ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
+ pInStr->RcRoiCtrl &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->RcRoiCtrl |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ pInStr->RoiBufferAddr = enc->roi_buf[buf_ctrl->old_val2].daddr;
+ mfc_debug(3, "[NALQ][ROI] buffer[%d] addr %#llx, QP val: %#x\n",
+ buf_ctrl->old_val2,
+ enc->roi_buf[buf_ctrl->old_val2].daddr,
+ buf_ctrl->val);
+ break;
+ case V4L2_CID_MPEG_VIDEO_YSUM:
+ pInStr->Weight &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->Weight |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ break;
+ case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
+ pInStr->RcMode &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ pInStr->RcMode |=
+ (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+ param_change = 1;
+ break;
+ /* If new dynamic controls are added, insert here */
+ default:
+ mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+ buf_ctrl->id);
+ }
+
+ if (param_change)
+ pInStr->ParamChange |= (1 << buf_ctrl->flag_shft);
+
+ buf_ctrl->has_new = 0;
+ buf_ctrl->updated = 1;
+
+ mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
+ pInStr->FixedPictureQp &= ~(0xFF000000);
+ pInStr->FixedPictureQp |= (p->config_qp & 0xFF) << 24;
+ mfc_debug(6, "[NALQ][CTRLS] Dynamic QP changed %#x\n",
+ pInStr->FixedPictureQp);
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int mfc_enc_get_buf_ctrls_val_nal_q_enc(struct mfc_ctx *ctx,
+ struct list_head *head, EncoderOutputStr *pOutStr)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_enc *enc = ctx->enc_priv;
+ unsigned int value = 0;
+
+ mfc_debug_enter();
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+ switch (buf_ctrl->id) {
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+ value = pOutStr->PictureTag;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
+ value = pOutStr->EncodedFrameAddr[0];
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
+ value = pOutStr->EncodedFrameAddr[1];
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+ value = !enc->in_slice;
+ break;
+ /* If new dynamic controls are added, insert here */
+ default:
+ mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+ buf_ctrl->id);
+ }
+ value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+ buf_ctrl->val = value;
+ buf_ctrl->has_new = 1;
+
+ mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int mfc_enc_recover_buf_ctrls_val(struct mfc_ctx *ctx,
+ struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dev *dev = ctx->dev;
+ unsigned int value = 0;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+ || !buf_ctrl->is_volatile
+ || !buf_ctrl->updated)
+ continue;
+
+ if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
+ value = MFC_READL(buf_ctrl->addr);
+
+ value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+ value |= ((buf_ctrl->old_val & buf_ctrl->mask)
+ << buf_ctrl->shft);
+
+ if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
+ MFC_WRITEL(value, buf_ctrl->addr);
+
+ /* clear change flag bit */
+ if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value &= ~(1 << buf_ctrl->flag_shft);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ }
+
+ mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
+ buf_ctrl->id, buf_ctrl->old_val);
+
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
+ value = MFC_READL(MFC_REG_E_GOP_CONFIG2);
+ value &= ~(0x3FFF);
+ value |= (buf_ctrl->old_val >> 16) & 0x3FFF;
+ MFC_WRITEL(value, MFC_REG_E_GOP_CONFIG2);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+ value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
+ value &= ~(0x000F);
+ value |= (buf_ctrl->old_val >> 8) & 0x000F;
+ MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+ value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
+ value &= ~(0xFF00);
+ value |= buf_ctrl->old_val & 0xFF00;
+ MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+ MFC_WRITEL(buf_ctrl->old_val, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+ MFC_WRITEL(buf_ctrl->old_val2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
+ }
+ if (buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
+ buf_ctrl->id
+ == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
+ MFC_WRITEL(buf_ctrl->old_val2, MFC_REG_E_NUM_T_LAYER);
+ /* clear RC_BIT_RATE_CHANGE */
+ value = MFC_READL(buf_ctrl->flag_addr);
+ value &= ~(1 << 2);
+ MFC_WRITEL(value, buf_ctrl->flag_addr);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+ value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
+ value &= ~(0x7 << 8);
+ value |= (buf_ctrl->old_val2 & 0x7) << 8;
+ MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+ }
+ if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+ value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
+ value &= ~(0xF << 11);
+ value |= (buf_ctrl->old_val2 & 0xF) << 11;
+ MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+ }
+ buf_ctrl->updated = 0;
+ }
+
+ return 0;
+}
+
+static int mfc_enc_recover_buf_ctrls_nal_q(struct mfc_ctx *ctx,
+ struct list_head *head)
+{
+ struct mfc_buf_ctrl *buf_ctrl;
+
+ list_for_each_entry(buf_ctrl, head, list) {
+ if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+ || !(buf_ctrl->updated))
+ continue;
+
+ buf_ctrl->has_new = 1;
+ buf_ctrl->updated = 0;
+
+ mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
+ buf_ctrl->id, buf_ctrl->val);
+ }
+
+ return 0;
+}
+
+struct mfc_ctrls_ops encoder_ctrls_ops = {
+ .init_ctx_ctrls = mfc_enc_init_ctx_ctrls,
+ .cleanup_ctx_ctrls = mfc_enc_cleanup_ctx_ctrls,
+ .init_buf_ctrls = mfc_enc_init_buf_ctrls,
+ .reset_buf_ctrls = mfc_enc_reset_buf_ctrls,
+ .cleanup_buf_ctrls = mfc_enc_cleanup_buf_ctrls,
+ .to_buf_ctrls = mfc_enc_to_buf_ctrls,
+ .to_ctx_ctrls = mfc_enc_to_ctx_ctrls,
+ .set_buf_ctrls_val = mfc_enc_set_buf_ctrls_val,
+ .get_buf_ctrls_val = mfc_enc_get_buf_ctrls_val,
+ .recover_buf_ctrls_val = mfc_enc_recover_buf_ctrls_val,
+ .get_buf_update_val = mfc_enc_get_buf_update_val,
+ .set_buf_ctrls_val_nal_q_enc = mfc_enc_set_buf_ctrls_val_nal_q_enc,
+ .get_buf_ctrls_val_nal_q_enc = mfc_enc_get_buf_ctrls_val_nal_q_enc,
+ .recover_buf_ctrls_nal_q = mfc_enc_recover_buf_ctrls_nal_q,
+};
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_enc_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_common.h"
-
-#include "mfc_reg.h"
-
-static int __mfc_enc_ctrl_read_cst(struct mfc_ctx *ctx,
- struct mfc_buf_ctrl *buf_ctrl)
-{
- int ret;
- struct mfc_enc *enc = ctx->enc_priv;
-
- switch (buf_ctrl->id) {
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
- ret = !enc->in_slice;
- break;
- default:
- mfc_err_ctx("not support custom per-buffer control\n");
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static struct mfc_ctrl_cfg mfc_ctrl_list[] = {
- { /* set frame tag */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_PICTURE_TAG,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* get frame tag */
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RET_PICTURE_TAG,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* encoded y physical addr */
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* encoded c physical addr */
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_ENCODED_SOURCE_SECOND_ADDR,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* I, not coded frame insertion */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_FRAME_INSERTION,
- .mask = 0x3,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* I period change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_GOP_CONFIG,
- .mask = 0xFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 0,
- },
- { /* frame rate change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_FRAME_RATE,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 1,
- },
- { /* bit rate change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_BIT_RATE,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 2,
- },
- { /* frame status (in slice or not) */
- .type = MFC_CTRL_TYPE_GET_DST,
- .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS,
- .is_volatile = 0,
- .mode = MFC_CTRL_MODE_CST,
- .addr = 0,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- .read_cst = __mfc_enc_ctrl_read_cst,
- .write_cst = NULL,
- },
- { /* H.264 I frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.264 I frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.263 I frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.263 I frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* MPEG4 I frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* MPEG4 I frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP8 I frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP8 I frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP9 I frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP9 I frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* HEVC I frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* HEVC I frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.264 P frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.264 P frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.263 P frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.263 P frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* MPEG4 P frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* MPEG4 P frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP8 P frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP8 P frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP9 P frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* VP9 P frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* HEVC P frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* HEVC P frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.264 B frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 24,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.264 B frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 16,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* MPEG4 B frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 24,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* MPEG4 B frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 16,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* HEVC B frame QP Max change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 24,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* HEVC B frame QP Min change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_QP_BOUND_PB,
- .mask = 0xFF,
- .shft = 16,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 4,
- },
- { /* H.264 Dynamic Temporal Layer & bitrate change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 10,
- },
- { /* HEVC Dynamic Temporal Layer & bitrate change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 10,
- },
- { /* VP8 Dynamic Temporal Layer change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 10,
- },
- { /* VP9 Dynamic Temporal Layer change */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 10,
- },
- { /* set level */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_PICTURE_PROFILE,
- .mask = 0x000000FF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 5,
- },
- { /* set profile */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_PICTURE_PROFILE,
- .mask = 0x0000000F,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 5,
- },
- { /* set store LTR */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_H264_NAL_CONTROL,
- .mask = 0x00000003,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* set use LTR */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_H264_NAL_CONTROL,
- .mask = 0x00000003,
- .shft = 2,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* set base layer priority */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_H264_HD_SVC_EXTENSION_0,
- .mask = 0x0000003F,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 12,
- },
- { /* set QP per each frame */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_FIXED_PICTURE_QP,
- .mask = 0x000000FF,
- .shft = 24,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* Region-Of-Interest control */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_ROI_CONTROL,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_ROI_CTRL,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_addr = 0,
- .flag_shft = 0,
- },
- { /* set YSUM for weighted prediction */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_YSUM,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_WEIGHT_FOR_WEIGHTED_PREDICTION,
- .mask = 0xFFFFFFFF,
- .shft = 0,
- .flag_mode = MFC_CTRL_MODE_NONE,
- .flag_mode = 0,
- .flag_shft = 0,
- },
- { /* set base layer priority */
- .type = MFC_CTRL_TYPE_SET,
- .id = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA,
- .is_volatile = 1,
- .mode = MFC_CTRL_MODE_SFR,
- .addr = MFC_REG_E_RC_MODE,
- .mask = 0x000000FF,
- .shft = 8,
- .flag_mode = MFC_CTRL_MODE_SFR,
- .flag_addr = MFC_REG_E_PARAM_CHANGE,
- .flag_shft = 13,
- }
-};
-
-#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
-
-static int mfc_enc_cleanup_ctx_ctrls(struct mfc_ctx *ctx)
-{
- struct mfc_ctx_ctrl *ctx_ctrl;
-
- while (!list_empty(&ctx->ctrls)) {
- ctx_ctrl = list_entry((&ctx->ctrls)->next,
- struct mfc_ctx_ctrl, list);
- list_del(&ctx_ctrl->list);
- kfree(ctx_ctrl);
- }
-
- INIT_LIST_HEAD(&ctx->ctrls);
-
- return 0;
-}
-
-static int mfc_enc_get_buf_update_val(struct mfc_ctx *ctx,
- struct list_head *head, unsigned int id, int value)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (buf_ctrl->id == id) {
- buf_ctrl->val = value;
- mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- break;
- }
- }
-
- return 0;
-}
-
-static int mfc_enc_init_ctx_ctrls(struct mfc_ctx *ctx)
-{
- unsigned long i;
- struct mfc_ctx_ctrl *ctx_ctrl;
-
- INIT_LIST_HEAD(&ctx->ctrls);
-
- for (i = 0; i < NUM_CTRL_CFGS; i++) {
- ctx_ctrl = kzalloc(sizeof(struct mfc_ctx_ctrl), GFP_KERNEL);
- if (ctx_ctrl == NULL) {
- mfc_err_dev("Failed to allocate context control "\
- "id: 0x%08x, type: %d\n",
- mfc_ctrl_list[i].id,
- mfc_ctrl_list[i].type);
-
- mfc_enc_cleanup_ctx_ctrls(ctx);
-
- return -ENOMEM;
- }
-
- ctx_ctrl->type = mfc_ctrl_list[i].type;
- ctx_ctrl->id = mfc_ctrl_list[i].id;
- ctx_ctrl->has_new = 0;
- ctx_ctrl->val = 0;
-
- list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
- }
-
- return 0;
-}
-
-static void mfc_enc_reset_buf_ctrls(struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- buf_ctrl->has_new = 0;
- buf_ctrl->val = 0;
- buf_ctrl->old_val = 0;
- buf_ctrl->updated = 0;
- }
-}
-
-static void __mfc_enc_remove_buf_ctrls(struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- while (!list_empty(head)) {
- buf_ctrl = list_entry(head->next,
- struct mfc_buf_ctrl, list);
- list_del(&buf_ctrl->list);
- kfree(buf_ctrl);
- }
-
- INIT_LIST_HEAD(head);
-}
-
-static int mfc_enc_init_buf_ctrls(struct mfc_ctx *ctx,
- enum mfc_ctrl_type type, unsigned int index)
-{
- unsigned long i;
- struct mfc_buf_ctrl *buf_ctrl;
- struct list_head *head;
-
- if (index >= MFC_MAX_BUFFERS) {
- mfc_err_dev("Per-buffer control index is out of range\n");
- return -EINVAL;
- }
-
- if (type & MFC_CTRL_TYPE_SRC) {
- if (test_bit(index, &ctx->src_ctrls_avail)) {
- mfc_enc_reset_buf_ctrls(&ctx->src_ctrls[index]);
-
- return 0;
- }
-
- head = &ctx->src_ctrls[index];
- } else if (type & MFC_CTRL_TYPE_DST) {
- if (test_bit(index, &ctx->dst_ctrls_avail)) {
- mfc_enc_reset_buf_ctrls(&ctx->dst_ctrls[index]);
-
- return 0;
- }
-
- head = &ctx->dst_ctrls[index];
- } else {
- mfc_err_dev("Control type mismatch. type : %d\n", type);
- return -EINVAL;
- }
-
- INIT_LIST_HEAD(head);
-
- for (i = 0; i < NUM_CTRL_CFGS; i++) {
- if (!(type & mfc_ctrl_list[i].type))
- continue;
-
- buf_ctrl = kzalloc(sizeof(struct mfc_buf_ctrl), GFP_KERNEL);
- if (buf_ctrl == NULL) {
- mfc_err_dev("Failed to allocate buffer control "\
- "id: 0x%08x, type: %d\n",
- mfc_ctrl_list[i].id,
- mfc_ctrl_list[i].type);
-
- __mfc_enc_remove_buf_ctrls(head);
-
- return -ENOMEM;
- }
-
- buf_ctrl->type = mfc_ctrl_list[i].type;
- buf_ctrl->id = mfc_ctrl_list[i].id;
- buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
- buf_ctrl->mode = mfc_ctrl_list[i].mode;
- buf_ctrl->addr = mfc_ctrl_list[i].addr;
- buf_ctrl->mask = mfc_ctrl_list[i].mask;
- buf_ctrl->shft = mfc_ctrl_list[i].shft;
- buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
- buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
- buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
- if (buf_ctrl->mode == MFC_CTRL_MODE_CST) {
- buf_ctrl->read_cst = mfc_ctrl_list[i].read_cst;
- buf_ctrl->write_cst = mfc_ctrl_list[i].write_cst;
- }
-
- list_add_tail(&buf_ctrl->list, head);
- }
-
- mfc_enc_reset_buf_ctrls(head);
-
- if (type & MFC_CTRL_TYPE_SRC)
- set_bit(index, &ctx->src_ctrls_avail);
- else
- set_bit(index, &ctx->dst_ctrls_avail);
-
- return 0;
-}
-
-static int mfc_enc_cleanup_buf_ctrls(struct mfc_ctx *ctx,
- enum mfc_ctrl_type type, unsigned int index)
-{
- struct list_head *head;
-
- if (index >= MFC_MAX_BUFFERS) {
- mfc_err_dev("Per-buffer control index is out of range\n");
- return -EINVAL;
- }
-
- if (type & MFC_CTRL_TYPE_SRC) {
- if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
- return 0;
- }
-
- head = &ctx->src_ctrls[index];
- } else if (type & MFC_CTRL_TYPE_DST) {
- if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
- return 0;
- }
-
- head = &ctx->dst_ctrls[index];
- } else {
- mfc_err_dev("Control type mismatch. type : %d\n", type);
- return -EINVAL;
- }
-
- __mfc_enc_remove_buf_ctrls(head);
-
- return 0;
-}
-
-static int mfc_enc_to_buf_ctrls(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_ctx_ctrl *ctx_ctrl;
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_enc *enc = ctx->enc_priv;
- int index = 0;
- unsigned int reg = 0;
-
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
- continue;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
- continue;
-
- if (buf_ctrl->id == ctx_ctrl->id) {
- buf_ctrl->has_new = 1;
- buf_ctrl->val = ctx_ctrl->val;
- if (buf_ctrl->is_volatile)
- buf_ctrl->updated = 0;
-
- ctx_ctrl->has_new = 0;
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
- index = enc->roi_index;
- if (enc->roi_info[index].enable) {
- enc->roi_index =
- (index + 1) % MFC_MAX_EXTRA_BUF;
- reg |= enc->roi_info[index].enable;
- reg &= ~(0xFF << 8);
- reg |= (enc->roi_info[index].lower_qp << 8);
- reg &= ~(0xFFFF << 16);
- reg |= (enc->roi_info[index].upper_qp << 16);
- mfc_debug(3, "[ROI] buffer[%d] en %d, "\
- "QP lower %d upper %d reg %#x\n",
- index, enc->roi_info[index].enable,
- enc->roi_info[index].lower_qp,
- enc->roi_info[index].upper_qp,
- reg);
- } else {
- mfc_debug(3, "[ROI] buffer[%d] is not enabled\n", index);
- }
- buf_ctrl->val = reg;
- buf_ctrl->old_val2 = index;
- }
- break;
- }
- }
- }
-
- return 0;
-}
-
-static int mfc_enc_to_ctx_ctrls(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_ctx_ctrl *ctx_ctrl;
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
- continue;
-
- list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
- if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
-
- if (ctx_ctrl->id == buf_ctrl->id) {
- if (ctx_ctrl->has_new)
- mfc_debug(8,
- "Overwrite context control "\
- "value id: 0x%08x, val: %d\n",
- ctx_ctrl->id, ctx_ctrl->val);
-
- ctx_ctrl->has_new = 1;
- ctx_ctrl->val = buf_ctrl->val;
-
- buf_ctrl->has_new = 0;
- }
- }
- }
-
- return 0;
-}
-
-static void __mfc_enc_set_buf_ctrls_temporal_svc(struct mfc_ctx *ctx,
- struct mfc_buf_ctrl *buf_ctrl)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- unsigned int value = 0, value2 = 0;
- struct temporal_layer_info temporal_LC;
- unsigned int i;
- struct mfc_enc_params *p = &enc->params;
-
- if (buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
- buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
- buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH ||
- buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
- memcpy(&temporal_LC,
- enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
-
- if(((temporal_LC.temporal_layer_count & 0x7) < 1) ||
- ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
- ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
- /* clear NUM_T_LAYER_CHANGE */
- value = MFC_READL(buf_ctrl->flag_addr);
- value &= ~(1 << 10);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- mfc_err_ctx("[HIERARCHICAL] layer count is invalid : %d\n",
- temporal_LC.temporal_layer_count);
- return;
- }
-
- if (IS_H264_ENC(ctx))
- p->codec.h264.num_hier_layer = temporal_LC.temporal_layer_count & 0x7;
-
- /* enable RC_BIT_RATE_CHANGE */
- value = MFC_READL(buf_ctrl->flag_addr);
- if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
- /* set RC_BIT_RATE_CHANGE */
- value |= (1 << 2);
- else
- /* clear RC_BIT_RATE_CHANGE */
- value &= ~(1 << 2);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
-
- mfc_debug(3, "[HIERARCHICAL] layer count %d, E_PARAM_CHANGE %#x\n",
- temporal_LC.temporal_layer_count & 0x7, value);
-
- value = MFC_READL(MFC_REG_E_NUM_T_LAYER);
- buf_ctrl->old_val2 = value;
- value &= ~(0x7);
- value |= (temporal_LC.temporal_layer_count & 0x7);
- value &= ~(0x1 << 8);
- value |= (p->hier_bitrate_ctrl & 0x1) << 8;
- MFC_WRITEL(value, MFC_REG_E_NUM_T_LAYER);
- mfc_debug(3, "[HIERARCHICAL] E_NUM_T_LAYER %#x\n", value);
- for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
- mfc_debug(3, "[HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
- i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
- MFC_WRITEL(temporal_LC.temporal_layer_bitrate[i],
- buf_ctrl->addr + i * 4);
- }
- /* priority change */
- if (IS_H264_ENC(ctx)) {
- value = 0;
- value2 = 0;
- for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
- if (i <= 4)
- value |= ((p->codec.h264.base_priority & 0x3F) + i)
- << (6 * i);
- else
- value2 |= ((p->codec.h264.base_priority & 0x3F) + i)
- << (6 * (i - 5));
- }
- MFC_WRITEL(value, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
- MFC_WRITEL(value2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
- mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
- value, value2);
-
- value = MFC_READL(buf_ctrl->flag_addr);
- value |= (1 << 12);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- mfc_debug(3, "[HIERARCHICAL] E_PARAM_CHANGE %#x\n", value);
- }
-
- }
-
- /* temproral layer priority */
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
- value = MFC_READL(MFC_REG_E_H264_HD_SVC_EXTENSION_0);
- buf_ctrl->old_val |= value & 0x3FFFFFC0;
- value &= ~(0x3FFFFFC0);
- value2 = MFC_READL(MFC_REG_E_H264_HD_SVC_EXTENSION_1);
- buf_ctrl->old_val2 = value2 & 0x0FFF;
- value2 &= ~(0x0FFF);
- for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
- if (i <= 4)
- value |= ((buf_ctrl->val & 0x3F) + i) << (6 * i);
- else
- value2 |= ((buf_ctrl->val & 0x3F) + i) << (6 * (i - 5));
- }
- MFC_WRITEL(value, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
- MFC_WRITEL(value2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
- p->codec.h264.base_priority = buf_ctrl->val;
- mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
- value, value2);
- }
-}
-
-static void __mfc_enc_set_buf_ctrls_exception(struct mfc_ctx *ctx,
- struct mfc_buf_ctrl *buf_ctrl)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_enc_params *p = &enc->params;
- unsigned int value = 0;
-
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
- enc->stored_tag = buf_ctrl->val;
-
- /* temporal layer setting */
- __mfc_enc_set_buf_ctrls_temporal_svc(ctx, buf_ctrl);
-
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
- value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
- buf_ctrl->old_val2 = (value >> 8) & 0x7;
- value &= ~(0x7 << 8);
- value |= (buf_ctrl->val & 0x7) << 8;
- MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
- }
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
- value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
- buf_ctrl->old_val2 = (value >> 11) & 0xF;
- value &= ~(0xF << 11);
- value |= (buf_ctrl->val & 0xF) << 11;
- MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
- }
-
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
- value = MFC_READL(MFC_REG_E_GOP_CONFIG2);
- buf_ctrl->old_val |= (value << 16) & 0x3FFF0000;
- value &= ~(0x3FFF);
- value |= (buf_ctrl->val >> 16) & 0x3FFF;
- MFC_WRITEL(value, MFC_REG_E_GOP_CONFIG2);
- }
-
- /* PROFILE & LEVEL have to be set up together */
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
- value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
- buf_ctrl->old_val |= (value & 0x000F) << 8;
- value &= ~(0x000F);
- value |= p->codec.h264.profile & 0x000F;
- MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
- p->codec.h264.level = buf_ctrl->val;
- }
-
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
- value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
- buf_ctrl->old_val |= value & 0xFF00;
- value &= ~(0x00FF << 8);
- value |= (p->codec.h264.level << 8) & 0xFF00;
- MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
- p->codec.h264.profile = buf_ctrl->val;
- }
-
- /* per buffer QP setting change */
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_CONFIG_QP)
- p->config_qp = buf_ctrl->val;
-
- /* set the ROI buffer DVA */
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
- MFC_WRITEL(enc->roi_buf[buf_ctrl->old_val2].daddr,
- MFC_REG_E_ROI_BUFFER_ADDR);
- mfc_debug(3, "[ROI] buffer[%d] addr %#llx, QP val: %#x\n",
- buf_ctrl->old_val2,
- enc->roi_buf[buf_ctrl->old_val2].daddr,
- buf_ctrl->val);
- }
-}
-
-static int mfc_enc_set_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- unsigned int value = 0;
- struct mfc_enc_params *p = &enc->params;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
- continue;
-
- /* read old vlaue */
- value = MFC_READL(buf_ctrl->addr);
-
- /* save old value for recovery */
- if (buf_ctrl->is_volatile)
- buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
- /* write new value */
- value &= ~(buf_ctrl->mask << buf_ctrl->shft);
- value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
- MFC_WRITEL(value, buf_ctrl->addr);
-
- /* set change flag bit */
- if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
- value = MFC_READL(buf_ctrl->flag_addr);
- value |= (1 << buf_ctrl->flag_shft);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- }
-
- buf_ctrl->has_new = 0;
- buf_ctrl->updated = 1;
-
- __mfc_enc_set_buf_ctrls_exception(ctx, buf_ctrl);
-
- mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
- value = MFC_READL(MFC_REG_E_FIXED_PICTURE_QP);
- value &= ~(0xFF000000);
- value |= (p->config_qp & 0xFF) << 24;
- MFC_WRITEL(value, MFC_REG_E_FIXED_PICTURE_QP);
- mfc_debug(6, "[CTRLS] Dynamic QP changed %#x\n",
- MFC_READL(MFC_REG_E_FIXED_PICTURE_QP));
- }
-
- return 0;
-}
-
-static int mfc_enc_get_buf_ctrls_val(struct mfc_ctx *ctx, struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dev *dev = ctx->dev;
- unsigned int value = 0;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
-
- if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
- value = MFC_READL(buf_ctrl->addr);
- else if (buf_ctrl->mode == MFC_CTRL_MODE_CST)
- value = call_bop(buf_ctrl, read_cst, ctx, buf_ctrl);
-
- value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
- buf_ctrl->val = value;
- buf_ctrl->has_new = 1;
-
- mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- return 0;
-}
-
-static int mfc_enc_set_buf_ctrls_val_nal_q_enc(struct mfc_ctx *ctx,
- struct list_head *head, EncoderInputStr *pInStr)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_enc *enc = ctx->enc_priv;
- struct temporal_layer_info temporal_LC;
- unsigned int i, param_change;
- struct mfc_enc_params *p = &enc->params;
-
- mfc_debug_enter();
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
- continue;
- param_change = 0;
- switch (buf_ctrl->id) {
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
- pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->PictureTag |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- enc->stored_tag = buf_ctrl->val;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
- pInStr->FrameInsertion &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->FrameInsertion |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
- pInStr->GopConfig &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->GopConfig |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- pInStr->GopConfig2 &= ~(0x3FFF);
- pInStr->GopConfig2 |= (buf_ctrl->val >> 16) & 0x3FFF;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
- pInStr->RcFrameRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->RcFrameRate |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
- pInStr->RcBitRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->RcBitRate |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
- case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
- pInStr->RcQpBound &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->RcQpBound |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
- case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
- case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
- pInStr->RcQpBoundPb &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->RcQpBoundPb |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
- case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
- memcpy(&temporal_LC,
- enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
-
- if (((temporal_LC.temporal_layer_count & 0x7) < 1) ||
- ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
- ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
- /* claer NUM_T_LAYER_CHANGE */
- mfc_err_ctx("[NALQ][HIERARCHICAL] layer count(%d) is invalid\n",
- temporal_LC.temporal_layer_count);
- return 0;
- }
-
- if (IS_H264_ENC(ctx))
- p->codec.h264.num_hier_layer =
- temporal_LC.temporal_layer_count & 0x7;
-
- /* enable RC_BIT_RATE_CHANGE */
- if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
- pInStr->ParamChange |= (1 << 2);
- else
- pInStr->ParamChange &= ~(1 << 2);
-
- /* enalbe NUM_T_LAYER_CHANGE */
- if (temporal_LC.temporal_layer_count & 0x7)
- pInStr->ParamChange |= (1 << 10);
- else
- pInStr->ParamChange &= ~(1 << 10);
- mfc_debug(3, "[NALQ][HIERARCHICAL] layer count %d\n",
- temporal_LC.temporal_layer_count & 0x7);
-
- pInStr->NumTLayer &= ~(0x7);
- pInStr->NumTLayer |= (temporal_LC.temporal_layer_count & 0x7);
- pInStr->NumTLayer &= ~(0x1 << 8);
- pInStr->NumTLayer |= (p->hier_bitrate_ctrl & 0x1) << 8;
- for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
- mfc_debug(3, "[NALQ][HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
- i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
- pInStr->HierarchicalBitRateLayer[i] =
- temporal_LC.temporal_layer_bitrate[i];
- }
-
- /* priority change */
- if (IS_H264_ENC(ctx)) {
- for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
- if (i <= 4)
- pInStr->H264HDSvcExtension0 |=
- ((p->codec.h264.base_priority & 0x3f) + i) << (6 * i);
- else
- pInStr->H264HDSvcExtension1 |=
- ((p->codec.h264.base_priority & 0x3f) + i) << (6 * (i - 5));
- }
- mfc_debug(3, "[NALQ][HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
- pInStr->H264HDSvcExtension0, pInStr->H264HDSvcExtension1);
-
- pInStr->ParamChange |= (1 << 12);
- }
- break;
- case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
- pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->PictureProfile |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- pInStr->PictureProfile &= ~(0xf);
- pInStr->PictureProfile |= p->codec.h264.profile & 0xf;
- p->codec.h264.level = buf_ctrl->val;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
- pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->PictureProfile |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- pInStr->PictureProfile &= ~(0xff << 8);
- pInStr->PictureProfile |= (p->codec.h264.level << 8) & 0xff00;
- p->codec.h264.profile = buf_ctrl->val;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
- pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->H264NalControl |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- pInStr->H264NalControl &= ~(0x7 << 8);
- pInStr->H264NalControl |= (buf_ctrl->val & 0x7) << 8;
- break;
- case V4L2_CID_MPEG_MFC_H264_USE_LTR:
- pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->H264NalControl |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- pInStr->H264NalControl &= ~(0xF << 11);
- pInStr->H264NalControl |= (buf_ctrl->val & 0xF) << 11;
- break;
- case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
- for (i = 0; i < (p->codec.h264.num_hier_layer & 0x7); i++)
- if (i <= 4)
- pInStr->H264HDSvcExtension0 |=
- ((buf_ctrl->val & 0x3f) + i) << (6 * i);
- else
- pInStr->H264HDSvcExtension1 |=
- ((buf_ctrl->val & 0x3f) + i) << (6 * (i - 5));
- p->codec.h264.base_priority = buf_ctrl->val;
- param_change = 1;
- break;
- case V4L2_CID_MPEG_MFC_CONFIG_QP:
- pInStr->FixedPictureQp &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->FixedPictureQp |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- p->config_qp = buf_ctrl->val;
- break;
- case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
- pInStr->RcRoiCtrl &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->RcRoiCtrl |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- pInStr->RoiBufferAddr = enc->roi_buf[buf_ctrl->old_val2].daddr;
- mfc_debug(3, "[NALQ][ROI] buffer[%d] addr %#llx, QP val: %#x\n",
- buf_ctrl->old_val2,
- enc->roi_buf[buf_ctrl->old_val2].daddr,
- buf_ctrl->val);
- break;
- case V4L2_CID_MPEG_VIDEO_YSUM:
- pInStr->Weight &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->Weight |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- break;
- case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
- pInStr->RcMode &= ~(buf_ctrl->mask << buf_ctrl->shft);
- pInStr->RcMode |=
- (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
- param_change = 1;
- break;
- /* If new dynamic controls are added, insert here */
- default:
- mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
- buf_ctrl->id);
- }
-
- if (param_change)
- pInStr->ParamChange |= (1 << buf_ctrl->flag_shft);
-
- buf_ctrl->has_new = 0;
- buf_ctrl->updated = 1;
-
- mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
- pInStr->FixedPictureQp &= ~(0xFF000000);
- pInStr->FixedPictureQp |= (p->config_qp & 0xFF) << 24;
- mfc_debug(6, "[NALQ][CTRLS] Dynamic QP changed %#x\n",
- pInStr->FixedPictureQp);
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int mfc_enc_get_buf_ctrls_val_nal_q_enc(struct mfc_ctx *ctx,
- struct list_head *head, EncoderOutputStr *pOutStr)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_enc *enc = ctx->enc_priv;
- unsigned int value = 0;
-
- mfc_debug_enter();
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
- continue;
- switch (buf_ctrl->id) {
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
- value = pOutStr->PictureTag;
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
- value = pOutStr->EncodedFrameAddr[0];
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
- value = pOutStr->EncodedFrameAddr[1];
- break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
- value = !enc->in_slice;
- break;
- /* If new dynamic controls are added, insert here */
- default:
- mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
- buf_ctrl->id);
- }
- value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
- buf_ctrl->val = value;
- buf_ctrl->has_new = 1;
-
- mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int mfc_enc_recover_buf_ctrls_val(struct mfc_ctx *ctx,
- struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
- struct mfc_dev *dev = ctx->dev;
- unsigned int value = 0;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
- || !buf_ctrl->is_volatile
- || !buf_ctrl->updated)
- continue;
-
- if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
- value = MFC_READL(buf_ctrl->addr);
-
- value &= ~(buf_ctrl->mask << buf_ctrl->shft);
- value |= ((buf_ctrl->old_val & buf_ctrl->mask)
- << buf_ctrl->shft);
-
- if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
- MFC_WRITEL(value, buf_ctrl->addr);
-
- /* clear change flag bit */
- if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
- value = MFC_READL(buf_ctrl->flag_addr);
- value &= ~(1 << buf_ctrl->flag_shft);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- }
-
- mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
- buf_ctrl->id, buf_ctrl->old_val);
-
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
- value = MFC_READL(MFC_REG_E_GOP_CONFIG2);
- value &= ~(0x3FFF);
- value |= (buf_ctrl->old_val >> 16) & 0x3FFF;
- MFC_WRITEL(value, MFC_REG_E_GOP_CONFIG2);
- }
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
- value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
- value &= ~(0x000F);
- value |= (buf_ctrl->old_val >> 8) & 0x000F;
- MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
- }
- if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
- value = MFC_READL(MFC_REG_E_PICTURE_PROFILE);
- value &= ~(0xFF00);
- value |= buf_ctrl->old_val & 0xFF00;
- MFC_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
- }
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
- MFC_WRITEL(buf_ctrl->old_val, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
- MFC_WRITEL(buf_ctrl->old_val2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
- }
- if (buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
- buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
- buf_ctrl->id
- == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
- MFC_WRITEL(buf_ctrl->old_val2, MFC_REG_E_NUM_T_LAYER);
- /* clear RC_BIT_RATE_CHANGE */
- value = MFC_READL(buf_ctrl->flag_addr);
- value &= ~(1 << 2);
- MFC_WRITEL(value, buf_ctrl->flag_addr);
- }
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
- value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
- value &= ~(0x7 << 8);
- value |= (buf_ctrl->old_val2 & 0x7) << 8;
- MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
- }
- if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
- value = MFC_READL(MFC_REG_E_H264_NAL_CONTROL);
- value &= ~(0xF << 11);
- value |= (buf_ctrl->old_val2 & 0xF) << 11;
- MFC_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
- }
- buf_ctrl->updated = 0;
- }
-
- return 0;
-}
-
-static int mfc_enc_recover_buf_ctrls_nal_q(struct mfc_ctx *ctx,
- struct list_head *head)
-{
- struct mfc_buf_ctrl *buf_ctrl;
-
- list_for_each_entry(buf_ctrl, head, list) {
- if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
- || !(buf_ctrl->updated))
- continue;
-
- buf_ctrl->has_new = 1;
- buf_ctrl->updated = 0;
-
- mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
- buf_ctrl->id, buf_ctrl->val);
- }
-
- return 0;
-}
-
-struct mfc_ctrls_ops encoder_ctrls_ops = {
- .init_ctx_ctrls = mfc_enc_init_ctx_ctrls,
- .cleanup_ctx_ctrls = mfc_enc_cleanup_ctx_ctrls,
- .init_buf_ctrls = mfc_enc_init_buf_ctrls,
- .reset_buf_ctrls = mfc_enc_reset_buf_ctrls,
- .cleanup_buf_ctrls = mfc_enc_cleanup_buf_ctrls,
- .to_buf_ctrls = mfc_enc_to_buf_ctrls,
- .to_ctx_ctrls = mfc_enc_to_ctx_ctrls,
- .set_buf_ctrls_val = mfc_enc_set_buf_ctrls_val,
- .get_buf_ctrls_val = mfc_enc_get_buf_ctrls_val,
- .recover_buf_ctrls_val = mfc_enc_recover_buf_ctrls_val,
- .get_buf_update_val = mfc_enc_get_buf_update_val,
- .set_buf_ctrls_val_nal_q_enc = mfc_enc_set_buf_ctrls_val_nal_q_enc,
- .get_buf_ctrls_val_nal_q_enc = mfc_enc_get_buf_ctrls_val_nal_q_enc,
- .recover_buf_ctrls_nal_q = mfc_enc_recover_buf_ctrls_nal_q,
-};
#include "mfc_enc_param.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
/* Definition */
#define FRAME_DELTA_DEFAULT 1
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_enc_v4l2.h"
+#include "mfc_enc_internal.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_otf.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static struct mfc_fmt *__mfc_enc_find_format(struct mfc_ctx *ctx,
+ unsigned int pixelformat)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_fmt *fmt = NULL;
+ unsigned long i;
+
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (enc_formats[i].fourcc == pixelformat) {
+ fmt = (struct mfc_fmt *)&enc_formats[i];
+ break;
+ }
+ }
+
+ if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
+ mfc_err_ctx("[FRAME] 10bit is not supported\n");
+ fmt = NULL;
+ }
+ if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
+ mfc_err_ctx("[FRAME] 422 is not supported\n");
+ fmt = NULL;
+ }
+ if (!dev->pdata->support_rgb && (fmt->type & MFC_FMT_RGB)) {
+ mfc_err_ctx("[FRAME] RGB is not supported\n");
+ fmt = NULL;
+ }
+
+ return fmt;
+}
+
+static struct v4l2_queryctrl *__mfc_enc_get_ctrl(int id)
+{
+ unsigned long i;
+
+ for (i = 0; i < NUM_CTRLS; ++i)
+ if (id == controls[i].id)
+ return &controls[i];
+ return NULL;
+}
+
+static int __mfc_enc_check_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct v4l2_queryctrl *c;
+
+ c = __mfc_enc_get_ctrl(ctrl->id);
+ if (!c) {
+ mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
+ return -EINVAL;
+ }
+
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_GOP_SIZE
+ && ctrl->value > c->maximum) {
+ mfc_info_ctx("GOP_SIZE is changed to max(%d -> %d)\n",
+ ctrl->value, c->maximum);
+ ctrl->value = c->maximum;
+ }
+
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER) {
+ if ((ctrl->value & ~(1 << 16)) < c->minimum || (ctrl->value & ~(1 << 16)) > c->maximum
+ || (c->step != 0 && (ctrl->value & ~(1 << 16)) % c->step != 0)) {
+ mfc_err_ctx("[CTRLS][HIERARCHICAL] Invalid control value for %#x (%#x)\n",
+ ctrl->id, ctrl->value);
+ return -ERANGE;
+ } else {
+ return 0;
+ }
+ }
+
+ if (ctrl->value < c->minimum || ctrl->value > c->maximum
+ || (c->step != 0 && ctrl->value % c->step != 0)) {
+ mfc_err_ctx("[CTRLS] Invalid control value for %#x (%#x)\n",
+ ctrl->id, ctrl->value);
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+static inline int __mfc_enc_h264_profile(struct mfc_ctx *ctx, int profile)
+{
+ int ret = 0;
+
+ switch (profile) {
+ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+ ret = MFC_REG_E_PROFILE_H264_MAIN;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+ ret = MFC_REG_E_PROFILE_H264_HIGH;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+ ret = MFC_REG_E_PROFILE_H264_BASELINE;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+ ret = MFC_REG_E_PROFILE_H264_CONSTRAINED_BASELINE;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
+ ret = MFC_REG_E_PROFILE_H264_CONSTRAINED_HIGH;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
+ strncpy(cap->card, "encoder", sizeof(cap->card) - 1);
+ cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+ | V4L2_CAP_VIDEO_OUTPUT
+ | V4L2_CAP_VIDEO_CAPTURE_MPLANE
+ | V4L2_CAP_VIDEO_OUTPUT_MPLANE
+ | V4L2_CAP_STREAMING
+ | V4L2_CAP_DEVICE_CAPS;
+
+ cap->capabilities = cap->device_caps;
+
+ return 0;
+}
+
+static int __mfc_enc_enum_fmt(struct mfc_dev *dev, struct v4l2_fmtdesc *f,
+ unsigned int type)
+{
+ struct mfc_fmt *fmt;
+ unsigned long i, j = 0;
+
+ for (i = 0; i < NUM_FORMATS; ++i) {
+ if (!(enc_formats[i].type & type))
+ continue;
+ if (!dev->pdata->support_10bit && (enc_formats[i].type & MFC_FMT_10BIT))
+ continue;
+ if (!dev->pdata->support_422 && (enc_formats[i].type & MFC_FMT_422))
+ continue;
+ if (!dev->pdata->support_rgb && (enc_formats[i].type & MFC_FMT_RGB))
+ continue;
+
+ if (j == f->index) {
+ fmt = &enc_formats[i];
+ strlcpy(f->description, fmt->name,
+ sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
+
+ return 0;
+ }
+
+ ++j;
+ }
+
+ return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+ struct v4l2_fmtdesc *f)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+
+ return __mfc_enc_enum_fmt(dev, f, MFC_FMT_STREAM);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+ struct v4l2_fmtdesc *f)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+
+ return __mfc_enc_enum_fmt(dev, f, MFC_FMT_FRAME);
+}
+
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+ struct mfc_raw_info *raw;
+ int i;
+
+ mfc_debug_enter();
+
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "enc dst g_fmt\n");
+ /* This is run on output (encoder dest) */
+ pix_fmt_mp->width = 0;
+ pix_fmt_mp->height = 0;
+ pix_fmt_mp->field = V4L2_FIELD_NONE;
+ pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
+ pix_fmt_mp->num_planes = ctx->dst_fmt->mem_planes;
+
+ pix_fmt_mp->plane_fmt[0].bytesperline = enc->dst_buf_size;
+ pix_fmt_mp->plane_fmt[0].sizeimage = enc->dst_buf_size;
+ } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src g_fmt\n");
+ /* This is run on capture (encoder src) */
+ raw = &ctx->raw_buf;
+
+ pix_fmt_mp->width = ctx->img_width;
+ pix_fmt_mp->height = ctx->img_height;
+ pix_fmt_mp->field = V4L2_FIELD_NONE;
+ pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
+ pix_fmt_mp->num_planes = ctx->src_fmt->mem_planes;
+ for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+ pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
+ pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
+ }
+ } else {
+ mfc_err_dev("invalid buf type (%d)\n", f->type);
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_fmt *fmt;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+ fmt = __mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
+ if (!fmt) {
+ mfc_err_dev("Unsupported format for %s\n",
+ V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __mfc_enc_check_format(struct mfc_ctx *ctx)
+{
+ switch (ctx->src_fmt->fourcc) {
+ case V4L2_PIX_FMT_NV16M_S10B:
+ case V4L2_PIX_FMT_NV61M_S10B:
+ case V4L2_PIX_FMT_NV16M_P210:
+ case V4L2_PIX_FMT_NV61M_P210:
+ mfc_debug(2, "[FRAME][10BIT] is 422 and 10bit format\n");
+ ctx->is_10bit = 1;
+ ctx->is_422 = 1;
+ break;
+ case V4L2_PIX_FMT_NV16M:
+ case V4L2_PIX_FMT_NV61M:
+ mfc_debug(2, "[FRAME] is 422 format\n");
+ ctx->is_10bit = 0;
+ ctx->is_422 = 1;
+ break;
+ case V4L2_PIX_FMT_NV12M_S10B:
+ case V4L2_PIX_FMT_NV12M_P010:
+ case V4L2_PIX_FMT_NV21M_S10B:
+ case V4L2_PIX_FMT_NV21M_P010:
+ mfc_debug(2, "[FRAME][10BIT] is 10bit format\n");
+ ctx->is_10bit = 1;
+ ctx->is_422 = 0;
+ break;
+ default:
+ ctx->is_10bit = 0;
+ ctx->is_422 = 0;
+ break;
+ }
+ mfc_debug(2, "[FRAME] 10bit: %d, 422: %d\n", ctx->is_10bit, ctx->is_422);
+}
+
+static int __mfc_enc_check_resolution(struct mfc_ctx *ctx)
+{
+ int max_width = 0, max_height = 0, min_width = 0, min_height = 0, swap_check = 0;
+
+ /* Check max resolution */
+ switch (ctx->codec_mode) {
+ case MFC_REG_CODEC_HEVC_ENC:
+ if (ctx->is_422) {
+ max_width = 65536;
+ max_height = 8192;
+ swap_check = 1;
+ } else {
+ max_width = 8192;
+ max_height = 8192;
+ }
+ break;
+ case MFC_REG_CODEC_BPG_ENC:
+ max_width = 65536;
+ max_height = 8192;
+ swap_check = 1;
+ break;
+ case MFC_REG_CODEC_H264_ENC:
+ case MFC_REG_CODEC_VP8_ENC:
+ max_width = 8192;
+ max_height = 8192;
+ break;
+ case MFC_REG_CODEC_VP9_ENC:
+ max_width = 4096;
+ max_height = 8192;
+ break;
+ case MFC_REG_CODEC_MPEG4_ENC:
+ max_width = 2048;
+ max_height = 2048;
+ break;
+ case MFC_REG_CODEC_H263_ENC:
+ max_width = 2048;
+ max_height = 1152;
+ break;
+ default:
+ mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
+ return -EINVAL;
+ }
+
+ if (swap_check) {
+ if (!((ctx->crop_width < max_width && ctx->crop_height < max_height) ||
+ (ctx->crop_width < max_height && ctx->crop_height < max_width))) {
+ mfc_err_ctx("Resolution is too big(%dx%d > %dxi%d or %dx%d\n",
+ ctx->crop_width, ctx->crop_height, max_width, max_height,
+ max_height, max_width);
+ return -EINVAL;
+ }
+ } else {
+ if (ctx->crop_width > max_width || ctx->crop_height > max_height) {
+ mfc_err_ctx("Resolution is too big(%dx%d > %dx%d)\n",
+ ctx->crop_width, ctx->crop_height, max_width, max_height);
+ return -EINVAL;
+ }
+ }
+
+ /* Check min resolution */
+ switch (ctx->codec_mode) {
+ case MFC_REG_CODEC_HEVC_ENC:
+ case MFC_REG_CODEC_BPG_ENC:
+ case MFC_REG_CODEC_VP9_ENC:
+ min_width = 64;
+ min_height = 64;
+ break;
+ case MFC_REG_CODEC_H264_ENC:
+ case MFC_REG_CODEC_VP8_ENC:
+ case MFC_REG_CODEC_MPEG4_ENC:
+ case MFC_REG_CODEC_H263_ENC:
+ min_width = 32;
+ min_height = 32;
+ break;
+ default:
+ mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
+ return -EINVAL;
+ }
+
+ if (ctx->crop_width < min_width || ctx->crop_height < min_height) {
+ mfc_err_ctx("Resolution is too small(%dx%d < %dx%d)\n",
+ ctx->crop_width, ctx->crop_height, min_width, min_height);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mfc_dev *dev = video_drvdata(file);
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+ int ret = 0;
+
+ mfc_debug_enter();
+
+ if (ctx->vq_dst.streaming) {
+ mfc_err_ctx("dst queue busy\n");
+ return -EBUSY;
+ }
+
+ ctx->dst_fmt = __mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
+ if (!ctx->dst_fmt) {
+ mfc_err_ctx("Unsupported format for destination\n");
+ return -EINVAL;
+ }
+
+ ctx->codec_mode = ctx->dst_fmt->codec_mode;
+ mfc_info_ctx("[STREAM] Enc dst codec(%d) : %s\n",
+ ctx->codec_mode, ctx->dst_fmt->name);
+
+ if (__mfc_enc_check_resolution(ctx)) {
+ mfc_err_ctx("Unsupported resolution\n");
+ return -EINVAL;
+ }
+
+ if (ctx->otf_handle) {
+ if (ctx->dst_fmt->fourcc != V4L2_PIX_FMT_H264 &&
+ ctx->dst_fmt->fourcc != V4L2_PIX_FMT_HEVC) {
+ mfc_err_ctx("[OTF] only H.264 and HEVC is supported\n");
+ return -EINVAL;
+ }
+ if (mfc_otf_init(ctx)) {
+ mfc_err_ctx("[OTF] otf_init failed\n");
+ mfc_otf_destroy(ctx);
+ return -EINVAL;
+ }
+ }
+
+ enc->dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
+ pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+
+ ret = mfc_alloc_instance_context(ctx);
+ if (ret) {
+ mfc_err_ctx("Failed to allocate enc instance[%d] buffers\n",
+ ctx->num);
+ return -ENOMEM;
+ }
+
+ mfc_change_state(ctx, MFCINST_INIT);
+
+ ctx->capture_state = QUEUE_FREE;
+
+ ret = mfc_alloc_enc_roi_buffer(ctx);
+ if (ret) {
+ mfc_err_ctx("[ROI] Failed to allocate ROI buffers\n");
+ mfc_release_instance_context(ctx);
+ return -ENOMEM;
+ }
+
+ MFC_TRACE_CTX_HWLOCK("**ENC s_fmt\n");
+
+ ret = mfc_get_hwlock_ctx(ctx);
+ if (ret < 0) {
+ mfc_err_dev("Failed to get hwlock\n");
+ mfc_release_instance_context(ctx);
+ mfc_release_enc_roi_buffer(ctx);
+ return -EBUSY;
+ }
+
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ ret = mfc_just_run(dev, ctx->num);
+ if (ret) {
+ mfc_err_ctx("Failed to run MFC\n");
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ mfc_release_instance_context(ctx);
+ mfc_release_enc_roi_buffer(ctx);
+ return -EIO;
+ }
+
+ if (mfc_wait_for_done_ctx(ctx,
+ MFC_REG_R2H_CMD_OPEN_INSTANCE_RET)) {
+ mfc_err_ctx("time out during open instance\n");
+ mfc_release_hwlock_ctx(ctx);
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ mfc_release_instance_context(ctx);
+ mfc_release_enc_roi_buffer(ctx);
+ return -EIO;
+ }
+ mfc_release_hwlock_ctx(ctx);
+
+ mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+
+ if (mfc_enc_ctx_ready(ctx))
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ if (ctx->otf_handle && mfc_otf_ctx_ready(ctx))
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ if (mfc_is_work_to_do(dev))
+ queue_work(dev->butler_wq, &dev->butler_work);
+
+ mfc_debug_leave();
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+ mfc_debug_enter();
+
+ if (ctx->vq_src.streaming) {
+ mfc_err_ctx("src queue busy\n");
+ return -EBUSY;
+ }
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip source s_fmt\n");
+ return 0;
+ }
+
+ ctx->src_fmt = __mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
+ if (!ctx->src_fmt) {
+ mfc_err_ctx("Unsupported format for source\n");
+ return -EINVAL;
+ }
+
+ if (ctx->src_fmt->mem_planes != pix_fmt_mp->num_planes) {
+ mfc_err_ctx("[FRAME] enc src plane number is different (%d != %d)\n",
+ ctx->src_fmt->mem_planes, pix_fmt_mp->num_planes);
+ return -EINVAL;
+ }
+
+ ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
+ ctx->img_width = pix_fmt_mp->width;
+ ctx->img_height = pix_fmt_mp->height;
+ ctx->buf_stride = pix_fmt_mp->plane_fmt[0].bytesperline;
+
+ __mfc_enc_check_format(ctx);
+
+ if (ctx->state == MFCINST_RUNNING) {
+ mfc_change_state(ctx, MFCINST_GOT_INST);
+ mfc_info_ctx("[DRC] Enc resolution is changed\n");
+ }
+
+ mfc_info_ctx("[FRAME] enc src pixelformat : %s\n", ctx->src_fmt->name);
+ mfc_info_ctx("[FRAME] resolution w: %d, h: %d, stride: %d\n",
+ pix_fmt_mp->width, pix_fmt_mp->height, ctx->buf_stride);
+
+ /*
+ * It should be keep till buffer size and stride was calculated.
+ * And it can be changed to real encoding size, if user call the s_crop.
+ */
+ ctx->crop_width = ctx->img_width;
+ ctx->crop_height = ctx->img_height;
+ mfc_enc_calc_src_size(ctx);
+
+ ctx->output_state = QUEUE_FREE;
+
+ mfc_debug_leave();
+ return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+
+ mfc_debug_enter();
+
+ cr->c.left = ctx->crop_left;
+ cr->c.top = ctx->crop_top;
+ cr->c.width = ctx->crop_width;
+ cr->c.height = ctx->crop_height;
+
+ mfc_debug(2, "[FRAME] enc crop w: %d, h: %d, offset l: %d t: %d\n",
+ ctx->crop_width, ctx->crop_height, ctx->crop_left, ctx->crop_top);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+
+ mfc_debug_enter();
+
+ if (cr->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_err_ctx("not supported type (It can only in the source)\n");
+ return -EINVAL;
+ }
+
+ if (cr->c.left < 0 || cr->c.top < 0) {
+ mfc_err_ctx("[FRAME] crop position is negative\n");
+ return -EINVAL;
+ }
+
+ if ((cr->c.height > ctx->img_height) || (cr->c.top > ctx->img_height) ||
+ (cr->c.width > ctx->img_width) || (cr->c.left > ctx->img_width) ||
+ (cr->c.left <= (ctx->img_width - cr->c.width)) ||
+ (cr->c.top <= (ctx->img_height - cr->c.height))) {
+ mfc_err_ctx("[FRAME] Out of crop range: (%d,%d,%d,%d) from %dx%d\n",
+ cr->c.left, cr->c.top, cr->c.width, cr->c.height,
+ ctx->img_width, ctx->img_height);
+ return -EINVAL;
+ }
+
+ ctx->crop_top = cr->c.top;
+ ctx->crop_left = cr->c.left;
+ ctx->crop_height = cr->c.height;
+ ctx->crop_width = cr->c.width;
+
+ mfc_debug(3, "[FRAME] enc original: %dx%d, crop: %dx%d, offset l: %d t: %d\n",
+ ctx->img_width, ctx->img_height,
+ ctx->crop_width, ctx->crop_height,
+ ctx->crop_left, ctx->crop_top);
+
+ return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = 0;
+
+ mfc_debug_enter();
+
+ if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+ mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
+ return -EINVAL;
+ }
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip reqbufs\n");
+ return 0;
+ }
+
+ if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "enc dst reqbuf(%d)\n", reqbufs->count);
+ if (reqbufs->count == 0) {
+ ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ ctx->capture_state = QUEUE_FREE;
+ return ret;
+ }
+
+ if (ctx->capture_state != QUEUE_FREE) {
+ mfc_err_ctx("invalid capture state: %d\n", ctx->capture_state);
+ return -EINVAL;
+ }
+
+ ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ if (ret) {
+ mfc_err_ctx("error in vb2_reqbufs() for E(D)\n");
+ return ret;
+ }
+
+ ctx->capture_state = QUEUE_BUFS_REQUESTED;
+ } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src reqbuf(%d)\n", reqbufs->count);
+ if (reqbufs->count == 0) {
+ ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+ ctx->output_state = QUEUE_FREE;
+ return ret;
+ }
+
+ if (ctx->output_state != QUEUE_FREE) {
+ mfc_err_ctx("invalid output state: %d\n", ctx->output_state);
+ return -EINVAL;
+ }
+
+ ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+ if (ret) {
+ mfc_err_ctx("error in vb2_reqbufs() for E(S)\n");
+ return ret;
+ }
+
+ ctx->output_state = QUEUE_BUFS_REQUESTED;
+ } else {
+ mfc_err_ctx("invalid buf type (%d)\n", reqbufs->type);
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = 0;
+
+ mfc_debug_enter();
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip source querybuf\n");
+ return 0;
+ }
+
+ if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "enc dst querybuf, state: %d\n", ctx->state);
+ ret = vb2_querybuf(&ctx->vq_dst, buf);
+ if (ret != 0) {
+ mfc_err_dev("enc dst: error in vb2_querybuf()\n");
+ return ret;
+ }
+ } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src querybuf, state: %d\n", ctx->state);
+ ret = vb2_querybuf(&ctx->vq_src, buf);
+ if (ret != 0) {
+ mfc_err_dev("enc src: error in vb2_querybuf()\n");
+ return ret;
+ }
+ } else {
+ mfc_err_dev("invalid buf type (%d)\n", buf->type);
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Queue a buffer */
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int i, ret = -EINVAL;
+
+ mfc_debug_enter();
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip qbuf\n");
+ return 0;
+ }
+
+ if (ctx->state == MFCINST_ERROR) {
+ mfc_err_ctx("Call on QBUF after unrecoverable error\n");
+ return -EIO;
+ }
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
+ mfc_err_ctx("multiplanar but length is zero\n");
+ return -EIO;
+ }
+
+ if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src buf[%d] Q\n", buf->index);
+ for (i = 0; i < ctx->src_fmt->num_planes; i++) {
+ if (!buf->m.planes[i].bytesused) {
+ mfc_debug(2, "[FRAME] enc src[%d] size zero, "
+ "changed to buf size %d\n",
+ i, buf->m.planes[i].length);
+ buf->m.planes[i].bytesused = buf->m.planes[i].length;
+ } else {
+ mfc_debug(2, "[FRAME] enc src[%d] size %d\n",
+ i, buf->m.planes[i].bytesused);
+ }
+ }
+ ret = vb2_qbuf(&ctx->vq_src, buf);
+ } else {
+ mfc_debug(4, "enc dst buf[%d] Q\n", buf->index);
+ ret = vb2_qbuf(&ctx->vq_dst, buf);
+ }
+
+ mfc_debug_leave();
+ return ret;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret;
+
+ mfc_debug_enter();
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip dqbuf\n");
+ return 0;
+ }
+
+ if (ctx->state == MFCINST_ERROR) {
+ mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
+ return -EIO;
+ }
+ if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src buf[%d] DQ\n", buf->index);
+ ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+ } else {
+ mfc_debug(4, "enc dst buf[%d] DQ\n", buf->index);
+ ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+ }
+ mfc_debug_leave();
+ return ret;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = -EINVAL;
+
+ mfc_debug_enter();
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip streamon\n");
+ return 0;
+ }
+
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src streamon\n");
+ ret = vb2_streamon(&ctx->vq_src, type);
+
+ if (!ret) {
+ mfc_qos_on(ctx);
+ }
+ } else {
+ mfc_debug(4, "enc dst streamon\n");
+ ret = vb2_streamon(&ctx->vq_dst, type);
+ }
+
+ mfc_debug(2, "src: %d, dst: %d, state = %d, dpb_count = %d\n",
+ mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+ mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+ ctx->state, ctx->dpb_count);
+ mfc_debug_leave();
+ return ret;
+}
+
+/* Stream off, which equals to a pause */
+static int vidioc_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret;
+
+ mfc_debug_enter();
+
+ if (ctx->otf_handle) {
+ mfc_info_ctx("[OTF] skip streamoff\n");
+ return 0;
+ }
+
+ ret = -EINVAL;
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src streamoff\n");
+ mfc_qos_reset_last_framerate(ctx);
+
+ ret = vb2_streamoff(&ctx->vq_src, type);
+ if (!ret)
+ mfc_qos_off(ctx);
+ } else {
+ mfc_debug(4, "enc dst streamoff\n");
+ ret = vb2_streamoff(&ctx->vq_dst, type);
+ }
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+/* Query a ctrl */
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ struct v4l2_queryctrl *c;
+
+ c = __mfc_enc_get_ctrl(qc->id);
+ if (!c) {
+ mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
+ return -EINVAL;
+ }
+
+ *qc = *c;
+ return 0;
+}
+
+static int __mfc_enc_ext_info(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ int val = 0;
+
+ val |= ENC_SET_SPARE_SIZE;
+ val |= ENC_SET_TEMP_SVC_CH;
+
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
+ val |= ENC_SET_SKYPE_FLAG;
+
+ val |= ENC_SET_ROI_CONTROL;
+ val |= ENC_SET_QP_BOUND_PB;
+ val |= ENC_SET_FIXED_SLICE;
+ val |= ENC_SET_PVC_MODE;
+ val |= ENC_SET_RATIO_OF_INTRA;
+
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc))
+ val |= ENC_SET_COLOR_ASPECT;
+
+ val |= ENC_SET_HP_BITRATE_CONTROL;
+
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_enc))
+ val |= ENC_SET_STATIC_INFO;
+
+ mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
+
+ return val;
+}
+
+static int __mfc_enc_get_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ int ret = 0;
+ int found = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_CACHEABLE:
+ mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_STREAM_SIZE:
+ ctrl->value = enc->dst_buf_size;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE:
+ ctrl->value = enc->frame_type;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
+ ctrl->value = MFCSTATE_PROCESSING;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+ case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
+ case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+ continue;
+
+ if (ctx_ctrl->id == ctrl->id) {
+ if (ctx_ctrl->has_new) {
+ ctx_ctrl->has_new = 0;
+ ctrl->value = ctx_ctrl->val;
+ } else {
+ mfc_debug(5, "[CTRLS] Control value "\
+ "is not up to date: "\
+ "0x%08x\n", ctrl->id);
+ return -EINVAL;
+ }
+
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+ return -EINVAL;
+ }
+ break;
+ case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
+ ctrl->value = dev->pdata->ip_ver;
+ break;
+ case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
+ ctrl->value = MFC_DRIVER_INFO;
+ break;
+ case V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE:
+ ctrl->value = MFC_LINEAR_BUF_SIZE;
+ break;
+ case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+ ctrl->value = ctx->qos_ratio;
+ break;
+ case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
+ ctrl->value = __mfc_enc_ext_info(ctx);
+ break;
+ case V4L2_CID_MPEG_VIDEO_BPG_HEADER_SIZE:
+ ctrl->value = enc->header_size;
+ break;
+ default:
+ mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+ ret = -EINVAL;
+ break;
+ }
+
+ mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+ return ret;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = 0;
+
+ mfc_debug_enter();
+ ret = __mfc_enc_get_ctrl_val(ctx, ctrl);
+ mfc_debug_leave();
+
+ return ret;
+}
+
+static inline int __mfc_enc_h264_level(enum v4l2_mpeg_video_h264_level lvl)
+{
+ static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_5_1 + 1] = {
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_1_0 */ 10,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_1B */ 9,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_1_1 */ 11,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_1_2 */ 12,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_1_3 */ 13,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_2_0 */ 20,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_2_1 */ 21,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_2_2 */ 22,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_3_0 */ 30,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_3_1 */ 31,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_3_2 */ 32,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_4_0 */ 40,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_4_1 */ 41,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_4_2 */ 42,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_5_0 */ 50,
+ /* V4L2_MPEG_VIDEO_H264_LEVEL_5_1 */ 51,
+ };
+ return t[lvl];
+}
+
+static inline int __mfc_enc_mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
+{
+ static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_6 + 1] = {
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 */ 0,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B, Simple */ 9,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 */ 1,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 */ 2,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 */ 3,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B, Advanced */ 7,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 */ 4,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 */ 5,
+ /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_6, Simple */ 6,
+ };
+ return t[lvl];
+}
+
+static inline int __mfc_enc_vui_sar_idc(enum v4l2_mpeg_video_h264_vui_sar_idc sar)
+{
+ static unsigned int t[V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED + 1] = {
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED */ 0,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1 */ 1,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11 */ 2,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11 */ 3,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11 */ 4,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33 */ 5,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11 */ 6,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11 */ 7,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11 */ 8,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33 */ 9,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11 */ 10,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11 */ 11,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33 */ 12,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99 */ 13,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3 */ 14,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2 */ 15,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 */ 16,
+ /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED */ 255,
+ };
+ return t[sar];
+}
+
+static int __mfc_enc_set_param(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_enc_params *p = &enc->params;
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ p->gop_size = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+ p->slice_mode =
+ (enum v4l2_mpeg_video_multi_slice_mode)ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+ p->slice_mb = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+ p->slice_bit = ctrl->value * 8;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW:
+ p->slice_mb_row = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+ p->intra_refresh_mb = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
+ p->pad = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
+ p->pad_luma = (ctrl->value >> 16) & 0xff;
+ p->pad_cb = (ctrl->value >> 8) & 0xff;
+ p->pad_cr = (ctrl->value >> 0) & 0xff;
+ break;
+ case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+ p->rc_frame = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_BITRATE:
+ p->rc_bitrate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
+ p->rc_reaction_coeff = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+ enc->force_frame_type = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
+ p->vbv_buf_size = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+ p->seq_hdr_mode =
+ (enum v4l2_mpeg_video_header_mode)(ctrl->value);
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
+ p->frame_skip_mode =
+ (enum v4l2_mpeg_mfc51_video_frame_skip_mode)
+ (ctrl->value);
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
+ p->fixed_target_bit = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+ p->num_b_frame = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ p->codec.h264.profile =
+ __mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+ p->codec.h264.level =
+ __mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE:
+ p->codec.h264.interlace = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+ p->codec.h264.loop_filter_mode =
+ (enum v4l2_mpeg_video_h264_loop_filter_mode)(ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+ p->codec.h264.loop_filter_alpha = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+ p->codec.h264.loop_filter_beta = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ p->codec.h264.entropy_mode =
+ (enum v4l2_mpeg_video_h264_entropy_mode)(ctrl->value);
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
+ p->num_refs_for_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+ p->codec.h264._8x8_transform = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+ p->rc_mb = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE:
+ p->rc_framerate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+ p->codec.h264.rc_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ p->codec.h264.rc_min_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ p->codec.h264.rc_max_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+ p->codec.h264.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+ p->codec.h264.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+ p->codec.h264.rc_min_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+ p->codec.h264.rc_max_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
+ p->codec.h264.rc_mb_dark = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
+ p->codec.h264.rc_mb_smooth = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
+ p->codec.h264.rc_mb_static = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
+ p->codec.h264.rc_mb_activity = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+ p->codec.h264.rc_p_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+ p->codec.h264.rc_b_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
+ p->codec.h264.ar_vui = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+ p->codec.h264.ar_vui_idc =
+ __mfc_enc_vui_sar_idc((enum v4l2_mpeg_video_h264_vui_sar_idc)(ctrl->value));
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
+ p->codec.h264.ext_sar_width = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
+ p->codec.h264.ext_sar_height = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+ p->codec.h264.open_gop = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+ p->codec.h264.open_gop_size = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:
+ p->codec.h264.hier_qp_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
+ p->codec.h264.hier_qp_type =
+ (enum v4l2_mpeg_video_h264_hierarchical_coding_type)(ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
+ p->codec.h264.num_hier_layer = ctrl->value & 0x7;
+ p->codec.h264.hier_ref_type = (ctrl->value >> 16) & 0x1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
+ p->codec.h264.hier_qp_layer[(ctrl->value >> 16) & 0x7]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0:
+ p->codec.h264.hier_bit_layer[0] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1:
+ p->codec.h264.hier_bit_layer[1] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2:
+ p->codec.h264.hier_bit_layer[2] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3:
+ p->codec.h264.hier_bit_layer[3] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4:
+ p->codec.h264.hier_bit_layer[4] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5:
+ p->codec.h264.hier_bit_layer[5] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6:
+ p->codec.h264.hier_bit_layer[6] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
+ p->codec.h264.sei_gen_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:
+ p->codec.h264.sei_fp_curr_frame_0 = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+ p->codec.h264.sei_fp_arrangement_type = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO:
+ p->codec.h264.fmo_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
+ switch ((enum v4l2_mpeg_video_h264_fmo_map_type)(ctrl->value)) {
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+ case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+ p->codec.h264.fmo_slice_map_type = ctrl->value;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:
+ p->codec.h264.fmo_slice_num_grp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:
+ p->codec.h264.fmo_run_length[(ctrl->value >> 30) & 0x3]
+ = ctrl->value & 0x3FFFFFFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:
+ p->codec.h264.fmo_sg_dir = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:
+ p->codec.h264.fmo_sg_rate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_ASO:
+ p->codec.h264.aso_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:
+ p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
+ &= ~(0xFF << (((ctrl->value >> 16) & 0x3) << 3));
+ p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
+ |= (ctrl->value & 0xFF) << \
+ (((ctrl->value >> 16) & 0x3) << 3);
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR:
+ p->codec.h264.prepend_sps_pps_to_idr = ctrl->value ? 1 : 0;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_ENABLE_LTR:
+ p->codec.h264.enable_ltr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR:
+ p->codec.h264.num_of_ltr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+ p->codec.h264.base_priority = ctrl->value;
+ p->codec.h264.set_priority = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+ switch ((enum v4l2_mpeg_video_mpeg4_profile)(ctrl->value)) {
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
+ p->codec.mpeg4.profile =
+ MFC_REG_E_PROFILE_MPEG4_SIMPLE;
+ break;
+ case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
+ p->codec.mpeg4.profile =
+ MFC_REG_E_PROFILE_MPEG4_ADVANCED_SIMPLE;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+ p->codec.mpeg4.level =
+ __mfc_enc_mpeg4_level((enum v4l2_mpeg_video_mpeg4_level)(ctrl->value));
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+ p->codec.mpeg4.rc_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ p->codec.mpeg4.rc_min_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ p->codec.mpeg4.rc_max_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+ p->codec.mpeg4.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+ p->codec.mpeg4.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+ p->codec.mpeg4.rc_min_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+ p->codec.mpeg4.rc_max_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
+ p->codec.mpeg4.quarter_pixel = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+ p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+ p->codec.mpeg4.rc_b_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES:
+ p->codec.mpeg4.vop_time_res = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA:
+ p->codec.mpeg4.vop_frm_delta = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE:
+ p->rc_framerate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+ p->codec.mpeg4.rc_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ p->codec.mpeg4.rc_min_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ p->codec.mpeg4.rc_max_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+ p->codec.mpeg4.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+ p->codec.mpeg4.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+ p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION:
+ p->codec.vp8.vp8_version = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE:
+ p->rc_framerate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
+ p->codec.vp8.rc_min_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
+ p->codec.vp8.rc_max_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+ p->codec.vp8.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+ p->codec.vp8.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP:
+ p->codec.vp8.rc_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP:
+ p->codec.vp8.rc_p_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS:
+ p->codec.vp8.vp8_numberofpartitions = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL:
+ p->codec.vp8.vp8_filterlevel = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS:
+ p->codec.vp8.vp8_filtersharpness = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL:
+ p->codec.vp8.vp8_goldenframesel = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD:
+ p->codec.vp8.vp8_gfrefreshperiod = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE:
+ p->codec.vp8.hier_qp_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0:
+ p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1:
+ p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2:
+ p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0:
+ p->codec.vp8.hier_bit_layer[0] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1:
+ p->codec.vp8.hier_bit_layer[1] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2:
+ p->codec.vp8.hier_bit_layer[2] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES:
+ p->num_refs_for_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4:
+ p->codec.vp8.intra_4x4mode_disable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER:
+ p->codec.vp8.num_hier_layer = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_VERSION:
+ p->codec.vp9.vp9_version = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE:
+ p->rc_framerate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
+ p->codec.vp9.rc_min_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
+ p->codec.vp9.rc_max_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
+ p->codec.vp9.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
+ p->codec.vp9.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP:
+ p->codec.vp9.rc_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP:
+ p->codec.vp9.rc_p_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL:
+ p->codec.vp9.vp9_goldenframesel = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD:
+ p->codec.vp9.vp9_gfrefreshperiod = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE:
+ p->codec.vp9.hier_qp_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP:
+ p->codec.vp9.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0:
+ p->codec.vp9.hier_bit_layer[0] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1:
+ p->codec.vp9.hier_bit_layer[1] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2:
+ p->codec.vp9.hier_bit_layer[2] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES:
+ p->num_refs_for_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER:
+ p->codec.vp9.num_hier_layer = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH:
+ p->codec.vp9.max_partition_depth = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT:
+ p->codec.vp9.intra_pu_split_disable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER:
+ p->ivf_header_disable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
+ p->codec.vp9.profile = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
+ p->codec.hevc.rc_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
+ p->codec.hevc.rc_p_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
+ p->codec.hevc.rc_b_frame_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE:
+ p->rc_framerate = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+ p->codec.hevc.rc_min_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+ p->codec.hevc.rc_max_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+ p->codec.hevc.rc_min_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+ p->codec.hevc.rc_max_qp_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+ p->codec.hevc.rc_min_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+ p->codec.hevc.rc_max_qp_b = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
+ p->codec.hevc.level = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
+ p->codec.hevc.profile = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK:
+ p->codec.hevc.rc_lcu_dark = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH:
+ p->codec.hevc.rc_lcu_smooth = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC:
+ p->codec.hevc.rc_lcu_static = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY:
+ p->codec.hevc.rc_lcu_activity = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG:
+ p->codec.hevc.tier_flag = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH:
+ p->codec.hevc.max_partition_depth = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES:
+ p->num_refs_for_p = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE:
+ p->codec.hevc.refreshtype = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE:
+ p->codec.hevc.const_intra_period_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE:
+ p->codec.hevc.lossless_cu_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE:
+ p->codec.hevc.wavefront_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE:
+ p->codec.hevc.loopfilter_disable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY:
+ p->codec.hevc.loopfilter_across = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE:
+ p->codec.hevc.enable_ltr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE:
+ p->codec.hevc.hier_qp_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE:
+ p->codec.hevc.hier_qp_type =
+ (enum v4l2_mpeg_video_hevc_hierarchical_coding_type)(ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:
+ p->codec.hevc.num_hier_layer = ctrl->value & 0x7;
+ p->codec.hevc.hier_ref_type = (ctrl->value >> 16) & 0x1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:
+ p->codec.hevc.hier_qp_layer[(ctrl->value >> 16) & 0x7]
+ = ctrl->value & 0xFF;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:
+ p->codec.hevc.hier_bit_layer[0] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:
+ p->codec.hevc.hier_bit_layer[1] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:
+ p->codec.hevc.hier_bit_layer[2] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:
+ p->codec.hevc.hier_bit_layer[3] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:
+ p->codec.hevc.hier_bit_layer[4] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:
+ p->codec.hevc.hier_bit_layer[5] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:
+ p->codec.hevc.hier_bit_layer[6] = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE:
+ p->codec.hevc.general_pb_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE:
+ p->codec.hevc.temporal_id_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG:
+ p->codec.hevc.strong_intra_smooth = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT:
+ p->codec.hevc.intra_pu_split_disable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION:
+ p->codec.hevc.tmv_prediction_disable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
+ p->codec.hevc.max_num_merge_mv = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE:
+ p->codec.hevc.encoding_nostartcode_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD:
+ p->codec.hevc.refreshperiod = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
+ p->codec.hevc.lf_beta_offset_div2 = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
+ p->codec.hevc.lf_tc_offset_div2 = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
+ p->codec.hevc.size_of_length_field = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF:
+ p->codec.hevc.user_ref = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF:
+ p->codec.hevc.store_ref = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_ROI_ENABLE:
+ p->roi_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE:
+ p->codec.h264.vui_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR:
+ p->codec.hevc.prepend_sps_pps_to_idr = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE:
+ p->dynamic_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC_CONFIG_QP:
+ p->config_qp = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE:
+ /* It is valid for H.264, HEVC, VP8, VP9 */
+ p->rc_pvc = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER:
+ p->num_hier_max_layer = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING:
+ break;
+ case V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE:
+ p->weighted_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_BPG_THUMBNAIL_SIZE:
+ /* It should be included when NAL_START */
+ p->codec.bpg.thumb_size = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_BPG_EXIF_SIZE:
+ /* It should be included when NAL_START */
+ p->codec.bpg.exif_size = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
+ p->ratio_intra = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
+ p->check_color_range = 1;
+ p->color_range = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
+ p->colour_primaries = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
+ p->transfer_characteristics = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
+ p->matrix_coefficients = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL:
+ p->hier_bitrate_ctrl = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE:
+ p->static_info_enable = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
+ p->max_pic_average_light = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
+ p->max_content_light = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
+ p->max_display_luminance = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
+ p->min_display_luminance = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
+ p->white_point = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
+ p->display_primaries_0 = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
+ p->display_primaries_1 = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
+ p->display_primaries_2 = ctrl->value;
+ break;
+ default:
+ mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int __mfc_enc_set_ctrl_val(struct mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_enc_params *p = &enc->params;
+ struct mfc_ctx_ctrl *ctx_ctrl;
+ int ret = 0;
+ int found = 0;
+ int index = 0;
+
+ mfc_debug(5, "[CTRLS] id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+ switch (ctrl->id) {
+ case V4L2_CID_CACHEABLE:
+ mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+ break;
+ case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+ ctx->qos_ratio = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+ case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+ case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
+ case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
+ case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
+ case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+ case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
+ case V4L2_CID_MPEG_MFC_H264_USE_LTR:
+ case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+ case V4L2_CID_MPEG_MFC_CONFIG_QP:
+ case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
+ case V4L2_CID_MPEG_VIDEO_YSUM:
+ case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
+ list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+ if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
+ continue;
+
+ if (ctx_ctrl->id == ctrl->id) {
+ ctx_ctrl->has_new = 1;
+ ctx_ctrl->val = ctrl->value;
+ if (ctx_ctrl->id == \
+ V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH) {
+ ctx_ctrl->val &= ~(0xFFFF << 16);
+ ctx_ctrl->val |= ctx_ctrl->val << 16;
+ ctx_ctrl->val &= ~(0xFFFF);
+ ctx_ctrl->val |= p->rc_frame_delta & 0xFFFF;
+ }
+ if (((ctx_ctrl->id == \
+ V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH) ||
+ (ctx_ctrl->id == \
+ V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH) ||
+ (ctx_ctrl->id == \
+ V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH) ||
+ (ctx_ctrl->id == \
+ V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH)) &&
+ (enc->sh_handle_svc.fd == -1)) {
+ enc->sh_handle_svc.fd = ctrl->value;
+ if (mfc_mem_get_user_shared_handle(ctx,
+ &enc->sh_handle_svc))
+ return -EINVAL;
+ else
+ mfc_debug(2, "[MEMINFO][HIERARCHICAL] shared handle fd: %d, vaddr: 0x%p\n",
+ enc->sh_handle_svc.fd,
+ enc->sh_handle_svc.vaddr);
+ }
+ if (ctx_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH &&
+ p->i_frm_ctrl_mode) {
+ ctx_ctrl->val = ctx_ctrl->val * (p->num_b_frame + 1);
+ if (ctx_ctrl->val >= 0x3FFFFFFF) {
+ mfc_info_ctx("I frame interval is bigger than max: %d\n",
+ ctx_ctrl->val);
+ ctx_ctrl->val = 0x3FFFFFFF;
+ }
+ }
+ if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL)
+ ctx_ctrl->val = __mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
+ if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE)
+ ctx_ctrl->val = __mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
+ if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+ if (enc->sh_handle_roi.fd == -1) {
+ enc->sh_handle_roi.fd = ctrl->value;
+ if (mfc_mem_get_user_shared_handle(ctx,
+ &enc->sh_handle_roi))
+ return -EINVAL;
+ else
+ mfc_debug(2, "[MEMINFO][ROI] shared handle fd: %d, vaddr: 0x%p\n",
+ enc->sh_handle_roi.fd,
+ enc->sh_handle_roi.vaddr);
+ }
+ index = enc->roi_index;
+ memcpy(&enc->roi_info[index],
+ enc->sh_handle_roi.vaddr,
+ sizeof(struct mfc_enc_roi_info));
+ if (copy_from_user(enc->roi_buf[index].vaddr,
+ enc->roi_info[index].addr,
+ enc->roi_info[index].size))
+ return -EFAULT;
+ }
+
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+ return -EINVAL;
+ }
+ break;
+ default:
+ ret = __mfc_enc_set_param(ctx, ctrl);
+ break;
+ }
+
+ return ret;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ int ret = 0;
+
+ mfc_debug_enter();
+
+ ret = __mfc_enc_check_ctrl_val(ctx, ctrl);
+ if (ret != 0)
+ return ret;
+
+ ret = __mfc_enc_set_ctrl_val(ctx, ctrl);
+
+ mfc_debug_leave();
+
+ return ret;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+ struct v4l2_ext_controls *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct v4l2_ext_control *ext_ctrl;
+ struct v4l2_control ctrl;
+ int i;
+ int ret = 0;
+
+ if (f->which != V4L2_CTRL_CLASS_MPEG)
+ return -EINVAL;
+
+ for (i = 0; i < f->count; i++) {
+ ext_ctrl = (f->controls + i);
+
+ ctrl.id = ext_ctrl->id;
+
+ ret = __mfc_enc_get_ctrl_val(ctx, &ctrl);
+ if (ret == 0) {
+ ext_ctrl->value = ctrl.value;
+ } else {
+ f->error_idx = i;
+ break;
+ }
+
+ mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
+ i, ext_ctrl->id, ext_ctrl->value);
+ }
+
+ return ret;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+ struct v4l2_ext_controls *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct v4l2_ext_control *ext_ctrl;
+ struct v4l2_control ctrl;
+ int i;
+ int ret = 0;
+
+ if (f->which != V4L2_CTRL_CLASS_MPEG)
+ return -EINVAL;
+
+ for (i = 0; i < f->count; i++) {
+ ext_ctrl = (f->controls + i);
+
+ ctrl.id = ext_ctrl->id;
+ ctrl.value = ext_ctrl->value;
+
+ ret = __mfc_enc_check_ctrl_val(ctx, &ctrl);
+ if (ret != 0) {
+ f->error_idx = i;
+ break;
+ }
+
+ ret = __mfc_enc_set_param(ctx, &ctrl);
+ if (ret != 0) {
+ f->error_idx = i;
+ break;
+ }
+
+ mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
+ i, ext_ctrl->id, ext_ctrl->value);
+ }
+
+ return ret;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+ struct v4l2_ext_controls *f)
+{
+ struct mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+ struct v4l2_ext_control *ext_ctrl;
+ struct v4l2_control ctrl;
+ int i;
+ int ret = 0;
+
+ if (f->which != V4L2_CTRL_CLASS_MPEG)
+ return -EINVAL;
+
+ for (i = 0; i < f->count; i++) {
+ ext_ctrl = (f->controls + i);
+
+ ctrl.id = ext_ctrl->id;
+ ctrl.value = ext_ctrl->value;
+
+ ret = __mfc_enc_check_ctrl_val(ctx, &ctrl);
+ if (ret != 0) {
+ f->error_idx = i;
+ break;
+ }
+
+ mfc_debug(2, "[%d] id: 0x%08x, value: %d\n", i, ext_ctrl->id, ext_ctrl->value);
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ioctl_ops mfc_enc_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+ .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+ .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
+ .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
+ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
+ .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
+ .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane,
+ .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out_mplane,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
+ .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
+ .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
+};
+
+const struct v4l2_ioctl_ops *mfc_get_enc_v4l2_ioctl_ops(void)
+{
+ return &mfc_enc_ioctl_ops;
+}
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_enc_v4l2.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_ENC_V4L2_H
+#define __MFC_ENC_V4L2_H __FILE__
+
+#include "mfc_common.h"
+
+const struct v4l2_ioctl_ops *mfc_get_enc_v4l2_ioctl_ops(void);
+
+#endif /* __MFC_ENC_V4L2_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_common.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static int mfc_enc_queue_setup(struct vb2_queue *vq,
+ unsigned int *buf_count, unsigned int *plane_count,
+ unsigned int psize[], struct device *alloc_devs[])
+{
+ struct mfc_dev *dev;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_raw_info *raw;
+ int i;
+
+ mfc_debug_enter();
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+
+ if (ctx->state != MFCINST_GOT_INST &&
+ vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_err_ctx("invalid state: %d\n", ctx->state);
+ return -EINVAL;
+ }
+ if (ctx->state >= MFCINST_FINISHING &&
+ vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_err_ctx("invalid state: %d\n", ctx->state);
+ return -EINVAL;
+ }
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(4, "enc dst\n");
+ if (ctx->dst_fmt)
+ *plane_count = ctx->dst_fmt->mem_planes;
+ else
+ *plane_count = MFC_ENC_CAP_PLANE_COUNT;
+
+ if (*buf_count < 1)
+ *buf_count = 1;
+ if (*buf_count > MFC_MAX_BUFFERS)
+ *buf_count = MFC_MAX_BUFFERS;
+
+ psize[0] = enc->dst_buf_size;
+ alloc_devs[0] = dev->device;
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ mfc_debug(4, "enc src\n");
+ raw = &ctx->raw_buf;
+
+ if (ctx->src_fmt)
+ *plane_count = ctx->src_fmt->mem_planes;
+ else
+ *plane_count = MFC_ENC_OUT_PLANE_COUNT;
+
+ if (*buf_count < 1)
+ *buf_count = 1;
+ if (*buf_count > MFC_MAX_BUFFERS)
+ *buf_count = MFC_MAX_BUFFERS;
+
+ if (*plane_count == 1) {
+ psize[0] = raw->total_plane_size;
+ alloc_devs[0] = dev->device;
+ } else {
+ for (i = 0; i < *plane_count; i++) {
+ psize[i] = raw->plane_size[i];
+ alloc_devs[i] = dev->device;
+ }
+ }
+ } else {
+ mfc_err_ctx("invalid queue type: %d\n", vq->type);
+ return -EINVAL;
+ }
+
+ mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
+ *buf_count, *plane_count, vq->type);
+ for (i = 0; i < *plane_count; i++)
+ mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static void mfc_enc_unlock(struct vb2_queue *q)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev = ctx->dev;
+
+ mutex_unlock(&dev->mfc_mutex);
+}
+
+static void mfc_enc_lock(struct vb2_queue *q)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev = ctx->dev;
+
+ mutex_lock(&dev->mfc_mutex);
+}
+
+static int mfc_enc_buf_init(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ int ret;
+
+ mfc_debug_enter();
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ ret = mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
+ if (ret < 0)
+ return ret;
+
+ if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
+ vb->index) < 0)
+ mfc_err_ctx("failed in init_buf_ctrls\n");
+
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ ret = mfc_check_vb_with_fmt(ctx->src_fmt, vb);
+ if (ret < 0)
+ return ret;
+
+ if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
+ vb->index) < 0)
+ mfc_err_ctx("failed in init_buf_ctrls\n");
+ } else {
+ mfc_err_ctx("inavlid queue type: %d\n", vq->type);
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+static int mfc_enc_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_raw_info *raw;
+ unsigned int index = vb->index;
+ struct mfc_buf *buf = vb_to_mfc_buf(vb);
+ struct dma_buf *bufcon_dmabuf[MFC_MAX_PLANES];
+ int i, mem_get_count = 0;
+ size_t buf_size;
+
+ mfc_debug_enter();
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ buf_size = vb2_plane_size(vb, 0);
+ mfc_debug(2, "[STREAM] vb size: %lu, calc size: %u\n",
+ buf_size, enc->dst_buf_size);
+
+ if (buf_size < enc->dst_buf_size) {
+ mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
+ buf_size, enc->dst_buf_size);
+ return -EINVAL;
+ }
+
+ buf->addr[0][0] = mfc_mem_get_daddr_vb(vb, 0);
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ raw = &ctx->raw_buf;
+ if (ctx->src_fmt->mem_planes == 1) {
+ buf_size = vb2_plane_size(vb, 0);
+ mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
+ buf_size, raw->total_plane_size);
+ if (buf_size < raw->total_plane_size) {
+ mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
+ buf_size, raw->total_plane_size);
+ return -EINVAL;
+ }
+ } else {
+ for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+ buf_size = vb2_plane_size(vb, i);
+ mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
+ i, buf_size, raw->plane_size[i]);
+ if (buf_size < raw->plane_size[i]) {
+ mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
+ i, buf_size, raw->plane_size[i]);
+ return -EINVAL;
+ }
+ }
+ }
+
+ for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+ bufcon_dmabuf[i] = dma_buf_get(vb->planes[i].m.fd);
+ if (IS_ERR(bufcon_dmabuf[i])) {
+ mfc_err_ctx("failed to get bufcon dmabuf\n");
+ goto err_mem_put;
+ }
+
+ mem_get_count++;
+ buf->num_bufs_in_batch = mfc_bufcon_get_buf_count(bufcon_dmabuf[i]);
+ mfc_debug(3, "[BUFCON] num bufs in batch: %d\n", buf->num_bufs_in_batch);
+ if (buf->num_bufs_in_batch == 0) {
+ mfc_err_ctx("[BUFCON] bufs count couldn't be zero\n");
+ goto err_mem_put;
+ }
+
+ if (buf->num_bufs_in_batch < 0)
+ buf->num_bufs_in_batch = 0;
+
+ if (!ctx->batch_mode && buf->num_bufs_in_batch > 0) {
+ ctx->batch_mode = 1;
+ mfc_debug(2, "[BUFCON] buffer batch mode enable\n");
+ }
+
+ if (buf->num_bufs_in_batch > 0) {
+ if (mfc_bufcon_get_daddr(ctx, buf, bufcon_dmabuf[i], i)) {
+ mfc_err_ctx("[BUFCON] failed to get daddr[%d] in buffer container\n", i);
+ goto err_mem_put;
+ }
+
+ ctx->framerate = buf->num_valid_bufs * ENC_DEFAULT_CAM_CAPTURE_FPS;
+ mfc_debug(3, "[BUFCON] framerate: %ld\n", ctx->framerate);
+
+ dma_buf_put(bufcon_dmabuf[i]);
+ } else {
+ dma_addr_t start_raw;
+
+ dma_buf_put(bufcon_dmabuf[i]);
+ start_raw = mfc_mem_get_daddr_vb(vb, 0);
+ if (start_raw == 0) {
+ mfc_err_ctx("Plane mem not allocated\n");
+ return -ENOMEM;
+ }
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
+ buf->addr[0][0] = start_raw;
+ buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
+ buf->addr[0][0] = start_raw;
+ buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
+ ctx->img_width,
+ ctx->img_height);
+ } else {
+ buf->addr[0][i] = mfc_mem_get_daddr_vb(vb, i);
+ }
+ }
+ }
+
+ if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in to_buf_ctrls\n");
+ } else {
+ mfc_err_ctx("inavlid queue type: %d\n", vq->type);
+ return -EINVAL;
+ }
+
+ mfc_debug_leave();
+ return 0;
+
+err_mem_put:
+ for (i = 0; i < mem_get_count; i++)
+ dma_buf_put(bufcon_dmabuf[i]);
+
+ return -ENOMEM;
+}
+
+static void mfc_enc_buf_finish(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ unsigned int index = vb->index;
+
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
+ mfc_err_ctx("failed in to_ctx_ctrls\n");
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in to_ctx_ctrls\n");
+ }
+}
+
+static void mfc_enc_buf_cleanup(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ unsigned int index = vb->index;
+
+ mfc_debug_enter();
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+ MFC_CTRL_TYPE_DST, index) < 0)
+ mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+ MFC_CTRL_TYPE_SRC, index) < 0)
+ mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+ } else {
+ mfc_err_ctx("mfc_enc_buf_cleanup: unknown queue type\n");
+ }
+
+ mfc_debug_leave();
+}
+
+static int mfc_enc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev = ctx->dev;
+
+ /* If context is ready then dev = work->data;schedule it to run */
+ if (mfc_enc_ctx_ready(ctx)) {
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ }
+
+ mfc_try_run(dev);
+
+ return 0;
+}
+
+static void mfc_enc_stop_streaming(struct vb2_queue *q)
+{
+ struct mfc_ctx *ctx = q->drv_priv;
+ struct mfc_dev *dev = ctx->dev;
+ int index = 0;
+ int aborted = 0;
+ int ret = 0;
+
+ mfc_info_ctx("enc stop_streaming is called, hwlock : %d, type : %d\n",
+ test_bit(ctx->num, &dev->hwlock.bits), q->type);
+ MFC_TRACE_CTX("** ENC streamoff(type:%d)\n", q->type);
+
+ /* If a H/W operation is in progress, wait for it complete */
+ if (need_to_wait_nal_abort(ctx)) {
+ if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_NAL_ABORT_RET)) {
+ mfc_err_ctx("time out during nal abort\n");
+ mfc_cleanup_work_bit_and_try_run(ctx);
+ }
+ aborted = 1;
+ }
+ MFC_TRACE_CTX_HWLOCK("**ENC streamoff(type:%d)\n", q->type);
+ ret = mfc_get_hwlock_ctx(ctx);
+ if (ret < 0) {
+ mfc_err_ctx("Failed to get hwlock\n");
+ return;
+ }
+
+ if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_cleanup_enc_dst_queue(ctx);
+
+ while (index < MFC_MAX_BUFFERS) {
+ index = find_next_bit(&ctx->dst_ctrls_avail,
+ MFC_MAX_BUFFERS, index);
+ if (index < MFC_MAX_BUFFERS)
+ call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
+ index++;
+ }
+ } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (ctx->state == MFCINST_RUNNING) {
+ mfc_change_state(ctx, MFCINST_FINISHING);
+ mfc_set_bit(ctx->num, &dev->work_bits);
+
+ while (mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED)) {
+ ret = mfc_just_run(dev, ctx->num);
+ if (ret) {
+ mfc_err_ctx("Failed to run MFC\n");
+ break;
+ }
+ if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_FRAME_DONE_RET)) {
+ mfc_err_ctx("Waiting for LAST_SEQ timed out\n");
+ break;
+ }
+ if (ctx->state == MFCINST_RUNNING) {
+ mfc_debug(2, "all encoded buffers out\n");
+ break;
+ }
+ }
+ }
+
+ mfc_move_all_bufs(&ctx->buf_queue_lock, &ctx->src_buf_queue,
+ &ctx->ref_buf_queue, MFC_QUEUE_ADD_BOTTOM);
+ mfc_cleanup_enc_src_queue(ctx);
+
+ while (index < MFC_MAX_BUFFERS) {
+ index = find_next_bit(&ctx->src_ctrls_avail,
+ MFC_MAX_BUFFERS, index);
+ if (index < MFC_MAX_BUFFERS)
+ call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
+ index++;
+ }
+ }
+
+ if (aborted || ctx->state == MFCINST_FINISHING)
+ mfc_change_state(ctx, MFCINST_RUNNING);
+
+ mfc_debug(2, "buffer cleanup is done in stop_streaming, type : %d\n", q->type);
+
+ mfc_clear_bit(ctx->num, &dev->work_bits);
+ mfc_release_hwlock_ctx(ctx);
+
+ if (mfc_is_work_to_do(dev))
+ queue_work(dev->butler_wq, &dev->butler_work);
+}
+
+static void mfc_enc_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct mfc_ctx *ctx = vq->drv_priv;
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_buf *buf = vb_to_mfc_buf(vb);
+ int i;
+
+ mfc_debug_enter();
+
+ buf->next_index = 0;
+ buf->done_index = 0;
+
+ if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr: 0x%08llx\n",
+ ctx->num, vb->index, buf->addr[0][0]);
+
+ /* Mark destination as available for use by MFC */
+ mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, buf);
+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ for (i = 0; i < ctx->src_fmt->mem_planes; i++)
+ mfc_debug(2, "[BUFINFO] ctx[%d] add src index: %d, addr[%d]: 0x%08llx\n",
+ ctx->num, vb->index, i, buf->addr[0][i]);
+ mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
+
+ if (debug_ts == 1)
+ mfc_info_ctx("[TS] framerate: %ld, timestamp: %lld\n",
+ ctx->framerate, buf->vb.vb2_buf.timestamp);
+
+ mfc_qos_update_last_framerate(ctx, buf->vb.vb2_buf.timestamp);
+ mfc_qos_update_framerate(ctx);
+ } else {
+ mfc_err_ctx("unsupported buffer type (%d)\n", vq->type);
+ }
+
+ if (mfc_enc_ctx_ready(ctx)) {
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ }
+ mfc_try_run(dev);
+
+ mfc_debug_leave();
+}
+
+struct vb2_ops mfc_enc_qops = {
+ .queue_setup = mfc_enc_queue_setup,
+ .wait_prepare = mfc_enc_unlock,
+ .wait_finish = mfc_enc_lock,
+ .buf_init = mfc_enc_buf_init,
+ .buf_prepare = mfc_enc_buf_prepare,
+ .buf_finish = mfc_enc_buf_finish,
+ .buf_cleanup = mfc_enc_buf_cleanup,
+ .start_streaming = mfc_enc_start_streaming,
+ .stop_streaming = mfc_enc_stop_streaming,
+ .buf_queue = mfc_enc_buf_queue,
+};
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_common.h"
-
-#include "mfc_hwlock.h"
-#include "mfc_nal_q.h"
-#include "mfc_opr.h"
-#include "mfc_sync.h"
-
-#include "mfc_qos.h"
-#include "mfc_queue.h"
-#include "mfc_utils.h"
-#include "mfc_buf.h"
-#include "mfc_mem.h"
-
-static int mfc_enc_queue_setup(struct vb2_queue *vq,
- unsigned int *buf_count, unsigned int *plane_count,
- unsigned int psize[], struct device *alloc_devs[])
-{
- struct mfc_dev *dev;
- struct mfc_ctx *ctx = vq->drv_priv;
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_raw_info *raw;
- int i;
-
- mfc_debug_enter();
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
-
- if (ctx->state != MFCINST_GOT_INST &&
- vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_err_ctx("invalid state: %d\n", ctx->state);
- return -EINVAL;
- }
- if (ctx->state >= MFCINST_FINISHING &&
- vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_err_ctx("invalid state: %d\n", ctx->state);
- return -EINVAL;
- }
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(4, "enc dst\n");
- if (ctx->dst_fmt)
- *plane_count = ctx->dst_fmt->mem_planes;
- else
- *plane_count = MFC_ENC_CAP_PLANE_COUNT;
-
- if (*buf_count < 1)
- *buf_count = 1;
- if (*buf_count > MFC_MAX_BUFFERS)
- *buf_count = MFC_MAX_BUFFERS;
-
- psize[0] = enc->dst_buf_size;
- alloc_devs[0] = dev->device;
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- mfc_debug(4, "enc src\n");
- raw = &ctx->raw_buf;
-
- if (ctx->src_fmt)
- *plane_count = ctx->src_fmt->mem_planes;
- else
- *plane_count = MFC_ENC_OUT_PLANE_COUNT;
-
- if (*buf_count < 1)
- *buf_count = 1;
- if (*buf_count > MFC_MAX_BUFFERS)
- *buf_count = MFC_MAX_BUFFERS;
-
- if (*plane_count == 1) {
- psize[0] = raw->total_plane_size;
- alloc_devs[0] = dev->device;
- } else {
- for (i = 0; i < *plane_count; i++) {
- psize[i] = raw->plane_size[i];
- alloc_devs[i] = dev->device;
- }
- }
- } else {
- mfc_err_ctx("invalid queue type: %d\n", vq->type);
- return -EINVAL;
- }
-
- mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
- *buf_count, *plane_count, vq->type);
- for (i = 0; i < *plane_count; i++)
- mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static void mfc_enc_unlock(struct vb2_queue *q)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev = ctx->dev;
-
- mutex_unlock(&dev->mfc_mutex);
-}
-
-static void mfc_enc_lock(struct vb2_queue *q)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev = ctx->dev;
-
- mutex_lock(&dev->mfc_mutex);
-}
-
-static int mfc_enc_buf_init(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- int ret;
-
- mfc_debug_enter();
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- ret = mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
- if (ret < 0)
- return ret;
-
- if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
- vb->index) < 0)
- mfc_err_ctx("failed in init_buf_ctrls\n");
-
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- ret = mfc_check_vb_with_fmt(ctx->src_fmt, vb);
- if (ret < 0)
- return ret;
-
- if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
- vb->index) < 0)
- mfc_err_ctx("failed in init_buf_ctrls\n");
- } else {
- mfc_err_ctx("inavlid queue type: %d\n", vq->type);
- return -EINVAL;
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-static int mfc_enc_buf_prepare(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_raw_info *raw;
- unsigned int index = vb->index;
- struct mfc_buf *buf = vb_to_mfc_buf(vb);
- struct dma_buf *bufcon_dmabuf[MFC_MAX_PLANES];
- int i, mem_get_count = 0;
- size_t buf_size;
-
- mfc_debug_enter();
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- buf_size = vb2_plane_size(vb, 0);
- mfc_debug(2, "[STREAM] vb size: %lu, calc size: %u\n",
- buf_size, enc->dst_buf_size);
-
- if (buf_size < enc->dst_buf_size) {
- mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
- buf_size, enc->dst_buf_size);
- return -EINVAL;
- }
-
- buf->addr[0][0] = mfc_mem_get_daddr_vb(vb, 0);
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- raw = &ctx->raw_buf;
- if (ctx->src_fmt->mem_planes == 1) {
- buf_size = vb2_plane_size(vb, 0);
- mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
- buf_size, raw->total_plane_size);
- if (buf_size < raw->total_plane_size) {
- mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
- buf_size, raw->total_plane_size);
- return -EINVAL;
- }
- } else {
- for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
- buf_size = vb2_plane_size(vb, i);
- mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
- i, buf_size, raw->plane_size[i]);
- if (buf_size < raw->plane_size[i]) {
- mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
- i, buf_size, raw->plane_size[i]);
- return -EINVAL;
- }
- }
- }
-
- for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
- bufcon_dmabuf[i] = dma_buf_get(vb->planes[i].m.fd);
- if (IS_ERR(bufcon_dmabuf[i])) {
- mfc_err_ctx("failed to get bufcon dmabuf\n");
- goto err_mem_put;
- }
-
- mem_get_count++;
- buf->num_bufs_in_batch = mfc_bufcon_get_buf_count(bufcon_dmabuf[i]);
- mfc_debug(3, "[BUFCON] num bufs in batch: %d\n", buf->num_bufs_in_batch);
- if (buf->num_bufs_in_batch == 0) {
- mfc_err_ctx("[BUFCON] bufs count couldn't be zero\n");
- goto err_mem_put;
- }
-
- if (buf->num_bufs_in_batch < 0)
- buf->num_bufs_in_batch = 0;
-
- if (!ctx->batch_mode && buf->num_bufs_in_batch > 0) {
- ctx->batch_mode = 1;
- mfc_debug(2, "[BUFCON] buffer batch mode enable\n");
- }
-
- if (buf->num_bufs_in_batch > 0) {
- if (mfc_bufcon_get_daddr(ctx, buf, bufcon_dmabuf[i], i)) {
- mfc_err_ctx("[BUFCON] failed to get daddr[%d] in buffer container\n", i);
- goto err_mem_put;
- }
-
- ctx->framerate = buf->num_valid_bufs * ENC_DEFAULT_CAM_CAPTURE_FPS;
- mfc_debug(3, "[BUFCON] framerate: %ld\n", ctx->framerate);
-
- dma_buf_put(bufcon_dmabuf[i]);
- } else {
- dma_addr_t start_raw;
-
- dma_buf_put(bufcon_dmabuf[i]);
- start_raw = mfc_mem_get_daddr_vb(vb, 0);
- if (start_raw == 0) {
- mfc_err_ctx("Plane mem not allocated\n");
- return -ENOMEM;
- }
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
- buf->addr[0][0] = start_raw;
- buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
- buf->addr[0][0] = start_raw;
- buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
- ctx->img_width,
- ctx->img_height);
- } else {
- buf->addr[0][i] = mfc_mem_get_daddr_vb(vb, i);
- }
- }
- }
-
- if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in to_buf_ctrls\n");
- } else {
- mfc_err_ctx("inavlid queue type: %d\n", vq->type);
- return -EINVAL;
- }
-
- mfc_debug_leave();
- return 0;
-
-err_mem_put:
- for (i = 0; i < mem_get_count; i++)
- dma_buf_put(bufcon_dmabuf[i]);
-
- return -ENOMEM;
-}
-
-static void mfc_enc_buf_finish(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- unsigned int index = vb->index;
-
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
- mfc_err_ctx("failed in to_ctx_ctrls\n");
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in to_ctx_ctrls\n");
- }
-}
-
-static void mfc_enc_buf_cleanup(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- unsigned int index = vb->index;
-
- mfc_debug_enter();
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- if (call_cop(ctx, cleanup_buf_ctrls, ctx,
- MFC_CTRL_TYPE_DST, index) < 0)
- mfc_err_ctx("failed in cleanup_buf_ctrls\n");
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (call_cop(ctx, cleanup_buf_ctrls, ctx,
- MFC_CTRL_TYPE_SRC, index) < 0)
- mfc_err_ctx("failed in cleanup_buf_ctrls\n");
- } else {
- mfc_err_ctx("mfc_enc_buf_cleanup: unknown queue type\n");
- }
-
- mfc_debug_leave();
-}
-
-static int mfc_enc_start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev = ctx->dev;
-
- /* If context is ready then dev = work->data;schedule it to run */
- if (mfc_enc_ctx_ready(ctx)) {
- mfc_set_bit(ctx->num, &dev->work_bits);
- }
-
- mfc_try_run(dev);
-
- return 0;
-}
-
-static void mfc_enc_stop_streaming(struct vb2_queue *q)
-{
- struct mfc_ctx *ctx = q->drv_priv;
- struct mfc_dev *dev = ctx->dev;
- int index = 0;
- int aborted = 0;
- int ret = 0;
-
- mfc_info_ctx("enc stop_streaming is called, hwlock : %d, type : %d\n",
- test_bit(ctx->num, &dev->hwlock.bits), q->type);
- MFC_TRACE_CTX("** ENC streamoff(type:%d)\n", q->type);
-
- /* If a H/W operation is in progress, wait for it complete */
- if (need_to_wait_nal_abort(ctx)) {
- if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_NAL_ABORT_RET)) {
- mfc_err_ctx("time out during nal abort\n");
- mfc_cleanup_work_bit_and_try_run(ctx);
- }
- aborted = 1;
- }
- MFC_TRACE_CTX_HWLOCK("**ENC streamoff(type:%d)\n", q->type);
- ret = mfc_get_hwlock_ctx(ctx);
- if (ret < 0) {
- mfc_err_ctx("Failed to get hwlock\n");
- return;
- }
-
- if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_cleanup_enc_dst_queue(ctx);
-
- while (index < MFC_MAX_BUFFERS) {
- index = find_next_bit(&ctx->dst_ctrls_avail,
- MFC_MAX_BUFFERS, index);
- if (index < MFC_MAX_BUFFERS)
- call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
- index++;
- }
- } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (ctx->state == MFCINST_RUNNING) {
- mfc_change_state(ctx, MFCINST_FINISHING);
- mfc_set_bit(ctx->num, &dev->work_bits);
-
- while (mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED)) {
- ret = mfc_just_run(dev, ctx->num);
- if (ret) {
- mfc_err_ctx("Failed to run MFC\n");
- break;
- }
- if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_FRAME_DONE_RET)) {
- mfc_err_ctx("Waiting for LAST_SEQ timed out\n");
- break;
- }
- if (ctx->state == MFCINST_RUNNING) {
- mfc_debug(2, "all encoded buffers out\n");
- break;
- }
- }
- }
-
- mfc_move_all_bufs(&ctx->buf_queue_lock, &ctx->src_buf_queue,
- &ctx->ref_buf_queue, MFC_QUEUE_ADD_BOTTOM);
- mfc_cleanup_enc_src_queue(ctx);
-
- while (index < MFC_MAX_BUFFERS) {
- index = find_next_bit(&ctx->src_ctrls_avail,
- MFC_MAX_BUFFERS, index);
- if (index < MFC_MAX_BUFFERS)
- call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
- index++;
- }
- }
-
- if (aborted || ctx->state == MFCINST_FINISHING)
- mfc_change_state(ctx, MFCINST_RUNNING);
-
- mfc_debug(2, "buffer cleanup is done in stop_streaming, type : %d\n", q->type);
-
- mfc_clear_bit(ctx->num, &dev->work_bits);
- mfc_release_hwlock_ctx(ctx);
-
- if (mfc_is_work_to_do(dev))
- queue_work(dev->butler_wq, &dev->butler_work);
-}
-
-static void mfc_enc_buf_queue(struct vb2_buffer *vb)
-{
- struct vb2_queue *vq = vb->vb2_queue;
- struct mfc_ctx *ctx = vq->drv_priv;
- struct mfc_dev *dev = ctx->dev;
- struct mfc_buf *buf = vb_to_mfc_buf(vb);
- int i;
-
- mfc_debug_enter();
-
- buf->next_index = 0;
- buf->done_index = 0;
-
- if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr: 0x%08llx\n",
- ctx->num, vb->index, buf->addr[0][0]);
-
- /* Mark destination as available for use by MFC */
- mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, buf);
- } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- for (i = 0; i < ctx->src_fmt->mem_planes; i++)
- mfc_debug(2, "[BUFINFO] ctx[%d] add src index: %d, addr[%d]: 0x%08llx\n",
- ctx->num, vb->index, i, buf->addr[0][i]);
- mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
-
- if (debug_ts == 1)
- mfc_info_ctx("[TS] framerate: %ld, timestamp: %lld\n",
- ctx->framerate, buf->vb.vb2_buf.timestamp);
-
- mfc_qos_update_last_framerate(ctx, buf->vb.vb2_buf.timestamp);
- mfc_qos_update_framerate(ctx);
- } else {
- mfc_err_ctx("unsupported buffer type (%d)\n", vq->type);
- }
-
- if (mfc_enc_ctx_ready(ctx)) {
- mfc_set_bit(ctx->num, &dev->work_bits);
- }
- mfc_try_run(dev);
-
- mfc_debug_leave();
-}
-
-struct vb2_ops mfc_enc_qops = {
- .queue_setup = mfc_enc_queue_setup,
- .wait_prepare = mfc_enc_unlock,
- .wait_finish = mfc_enc_lock,
- .buf_init = mfc_enc_buf_init,
- .buf_prepare = mfc_enc_buf_prepare,
- .buf_finish = mfc_enc_buf_finish,
- .buf_cleanup = mfc_enc_buf_cleanup,
- .start_streaming = mfc_enc_start_streaming,
- .stop_streaming = mfc_enc_stop_streaming,
- .buf_queue = mfc_enc_buf_queue,
-};
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_cal.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <trace/events/mfc.h>
+
+#include "mfc_hw_reg_api.h"
+#include "mfc_pm.h"
+
+/* Reset the device */
+int mfc_reset_mfc(struct mfc_dev *dev)
+{
+ int i;
+
+ mfc_debug_enter();
+
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+
+ /* Zero Initialization of MFC registers */
+ MFC_WRITEL(0, MFC_REG_RISC2HOST_CMD);
+ MFC_WRITEL(0, MFC_REG_HOST2RISC_CMD);
+ MFC_WRITEL(0, MFC_REG_FW_VERSION);
+
+ for (i = 0; i < MFC_REG_REG_CLEAR_COUNT; i++)
+ MFC_WRITEL(0, MFC_REG_REG_CLEAR_BEGIN + (i*4));
+
+ MFC_WRITEL(0x1FFF, MFC_REG_MFC_RESET);
+ MFC_WRITEL(0, MFC_REG_MFC_RESET);
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+void mfc_set_risc_base_addr(struct mfc_dev *dev,
+ enum mfc_buf_usage_type buf_type)
+{
+ struct mfc_special_buf *fw_buf;
+
+ fw_buf = &dev->fw_buf;
+
+ if (buf_type == MFCBUF_DRM)
+ fw_buf = &dev->drm_fw_buf;
+
+ MFC_WRITEL(fw_buf->daddr, MFC_REG_RISC_BASE_ADDRESS);
+ mfc_debug(2, "[MEMINFO][F/W] %s Base Address : %#x\n",
+ buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
+ MFC_TRACE_DEV("%s F/W Base Address : %#x\n",
+ buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
+}
+
+void mfc_cmd_host2risc(struct mfc_dev *dev, int cmd)
+{
+ mfc_debug(1, "Issue the command: %d\n", cmd);
+ MFC_TRACE_DEV(">> CMD : %d, (dev:0x%lx, bits:%lx, owned:%d, wl:%d, trans:%d)\n",
+ cmd, dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+ dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+ trace_mfc_frame_start(dev->curr_ctx, cmd, 0, 0);
+ /* Reset RISC2HOST command except nal q stop command */
+ if (cmd != MFC_REG_H2R_CMD_STOP_QUEUE)
+ MFC_WRITEL(0x0, MFC_REG_RISC2HOST_CMD);
+
+ /* Start the timeout watchdog */
+ if ((cmd != MFC_REG_H2R_CMD_NAL_QUEUE) && (cmd != MFC_REG_H2R_CMD_STOP_QUEUE))
+ mfc_watchdog_start_tick(dev);
+
+ if (dbg_enable) {
+ /* For FW debugging */
+ mfc_dbg_set_addr(dev);
+ mfc_dbg_enable(dev);
+ }
+
+ /* Issue the command */
+ MFC_WRITEL(cmd, MFC_REG_HOST2RISC_CMD);
+ MFC_WRITEL(0x1, MFC_REG_HOST2RISC_INT);
+}
+
+/* Check whether HW interrupt has occurred or not */
+int mfc_check_risc2host(struct mfc_dev *dev)
+{
+ if (mfc_pm_get_pwr_ref_cnt(dev) && mfc_pm_get_clk_ref_cnt(dev)) {
+ if (MFC_READL(MFC_REG_RISC2HOST_INT))
+ return MFC_READL(MFC_REG_RISC2HOST_CMD);
+ else
+ return 0;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_HW_REG_API_H
+#define __MFC_HW_REG_API_H __FILE__
+
+#include "mfc_reg_api.h"
+
+#include "mfc_common.h"
+
+#include "mfc_utils.h"
+
+#define mfc_get_int_reason() (MFC_READL(MFC_REG_RISC2HOST_CMD) \
+ & MFC_REG_RISC2HOST_CMD_MASK)
+#define mfc_clear_int_sfr() \
+ do { \
+ MFC_WRITEL(0, MFC_REG_RISC2HOST_CMD); \
+ MFC_WRITEL(0, MFC_REG_RISC2HOST_INT); \
+ } while (0)
+
+static inline int mfc_stop_bus(struct mfc_dev *dev)
+{
+ unsigned int status;
+ unsigned long timeout;
+
+ /* Reset */
+ MFC_WRITEL(0x1, MFC_REG_MFC_BUS_RESET_CTRL);
+
+ timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+ /* Check bus status */
+ do {
+ if (time_after(jiffies, timeout)) {
+ mfc_err_dev("Timeout while resetting MFC.\n");
+ return -EIO;
+ }
+ status = MFC_READL(MFC_REG_MFC_BUS_RESET_CTRL);
+ } while ((status & 0x2) == 0);
+
+ return 0;
+}
+
+static inline void mfc_start_bus(struct mfc_dev *dev)
+{
+ int val;
+
+ val = MFC_READL(MFC_REG_MFC_BUS_RESET_CTRL);
+ val &= ~(0x1);
+ MFC_WRITEL(val, MFC_REG_MFC_BUS_RESET_CTRL);
+}
+
+static inline void mfc_risc_on(struct mfc_dev *dev)
+{
+ mfc_clean_dev_int_flags(dev);
+
+ MFC_WRITEL(0x1, MFC_REG_RISC_ON);
+ MFC_WRITEL(0x0, MFC_REG_MFC_OFF);
+ mfc_debug(1, "RISC_ON\n");
+ MFC_TRACE_DEV(">> RISC ON\n");
+}
+
+static inline void mfc_risc_off(struct mfc_dev *dev)
+{
+ unsigned int status;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+ /* Check pending status */
+ do {
+ if (time_after(jiffies, timeout)) {
+ mfc_err_dev("Timeout while pendng clear\n");
+ mfc_err_dev("MFC access pending state: %#x\n", status);
+ mfc_err_dev("MFC access pending R: %#x, W: %#x\n",
+ MFC_READL(MFC_REG_MFC_RPEND),
+ MFC_READL(MFC_REG_MFC_WPEND));
+ break;
+ }
+ status = MFC_READL(MFC_REG_MFC_BUS_STATUS);
+ } while (status != 0);
+
+ MFC_WRITEL(0x0, MFC_REG_RISC_ON);
+}
+
+static inline void mfc_mfc_off(struct mfc_dev *dev)
+{
+ mfc_info_dev("MFC h/w state: %d\n",
+ MFC_READL(MFC_REG_MFC_STATE) & 0x7);
+ MFC_WRITEL(0x1, MFC_REG_MFC_OFF);
+}
+
+static inline void mfc_enable_all_clocks(struct mfc_dev *dev)
+{
+ /* Enable all FW clock gating */
+ MFC_WRITEL(0xFFFFFFFF, MFC_REG_MFC_FW_CLOCK);
+}
+
+int mfc_reset_mfc(struct mfc_dev *dev);
+void mfc_set_risc_base_addr(struct mfc_dev *dev,
+ enum mfc_buf_usage_type buf_type);
+void mfc_cmd_host2risc(struct mfc_dev *dev, int cmd);
+int mfc_check_risc2host(struct mfc_dev *dev);
+
+#endif /* __MFC_HW_REG_API_H */
#include "mfc_inst.h"
#include "mfc_pm.h"
#include "mfc_cmd.h"
-#include "mfc_cal.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_queue.h"
#include "mfc_utils.h"
#include "mfc_cmd.h"
#include "mfc_enc_param.h"
-#include "mfc_cal.h"
#include "mfc_perf_measure.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_utils.h"
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_irq.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "mfc_irq.h"
-
-#include "mfc_hwlock.h"
-#include "mfc_nal_q.h"
-#include "mfc_otf.h"
-#include "mfc_opr.h"
-#include "mfc_sync.h"
-
-#include "mfc_pm.h"
-#include "mfc_cal.h"
-#include "mfc_perf_measure.h"
-#include "mfc_reg.h"
-#include "mfc_mmcache.h"
-
-#include "mfc_qos.h"
-#include "mfc_queue.h"
-#include "mfc_buf.h"
-#include "mfc_mem.h"
-
-static void __mfc_handle_black_bar_info(struct mfc_dev *dev, struct mfc_ctx *ctx)
-{
- struct v4l2_rect new_black_bar;
- int black_bar_info;
- struct mfc_dec *dec = ctx->dec_priv;
-
- black_bar_info = mfc_get_black_bar_detection();
- mfc_debug(3, "[BLACKBAR] type: %#x\n", black_bar_info);
-
- if (black_bar_info == MFC_REG_DISP_STATUS_BLACK_BAR) {
- new_black_bar.left = mfc_get_black_bar_pos_x();
- new_black_bar.top = mfc_get_black_bar_pos_y();
- new_black_bar.width = mfc_get_black_bar_image_w();
- new_black_bar.height = mfc_get_black_bar_image_h();
- } else if (black_bar_info == MFC_REG_DISP_STATUS_BLACK_SCREEN) {
- new_black_bar.left = -1;
- new_black_bar.top = -1;
- new_black_bar.width = ctx->img_width;
- new_black_bar.height = ctx->img_height;
- } else if (black_bar_info == MFC_REG_DISP_STATUS_NOT_DETECTED) {
- new_black_bar.left = 0;
- new_black_bar.top = 0;
- new_black_bar.width = ctx->img_width;
- new_black_bar.height = ctx->img_height;
- } else {
- mfc_err_ctx("[BLACKBAR] Not supported type: %#x\n", black_bar_info);
- dec->black_bar_updated = 0;
- return;
- }
-
- if ((new_black_bar.left == dec->black_bar.left) &&
- (new_black_bar.top == dec->black_bar.top) &&
- (new_black_bar.width == dec->black_bar.width) &&
- (new_black_bar.height == dec->black_bar.height)) {
- mfc_debug(4, "[BLACKBAR] information was not changed\n");
- dec->black_bar_updated = 0;
- return;
- }
-
- dec->black_bar = new_black_bar;
- dec->black_bar_updated = 1;
-}
-
-static unsigned int __mfc_handle_frame_field(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- unsigned int interlace_type = 0, is_interlace = 0, is_mbaff = 0;
- unsigned int field;
-
- if (CODEC_INTERLACED(ctx))
- is_interlace = mfc_is_interlace_picture();
-
- if (CODEC_MBAFF(ctx))
- is_mbaff = mfc_is_mbaff_picture();
-
- if (is_interlace) {
- interlace_type = mfc_get_interlace_type();
- if (interlace_type)
- field = V4L2_FIELD_INTERLACED_TB;
- else
- field = V4L2_FIELD_INTERLACED_BT;
- } else if (is_mbaff) {
- field = V4L2_FIELD_INTERLACED_TB;
- } else {
- field = V4L2_FIELD_NONE;
- }
-
- mfc_debug(2, "[INTERLACE] is_interlace: %d (type : %d), is_mbaff: %d, field: 0x%#x\n",
- is_interlace, interlace_type, is_mbaff, field);
-
- return field;
-}
-
-static void __mfc_handle_frame_all_extracted(struct mfc_ctx *ctx)
-{
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_buf *dst_mb;
- int index, i, is_first = 1;
-
- mfc_debug(2, "Decided to finish\n");
- ctx->sequence++;
-
- while (1) {
- dst_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (!dst_mb)
- break;
-
- mfc_debug(2, "Cleaning up buffer: %d\n",
- dst_mb->vb.vb2_buf.index);
-
- index = dst_mb->vb.vb2_buf.index;
-
- for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
- vb2_set_plane_payload(&dst_mb->vb.vb2_buf, i, 0);
-
- dst_mb->vb.sequence = (ctx->sequence++);
- dst_mb->vb.field = __mfc_handle_frame_field(ctx);
- dst_mb->vb.reserved2 = 0;
-
- clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
-
- if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
- mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
- if (is_first) {
- call_cop(ctx, get_buf_update_val, ctx,
- &ctx->dst_ctrls[index],
- V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- dec->stored_tag);
- is_first = 0;
- } else {
- call_cop(ctx, get_buf_update_val, ctx,
- &ctx->dst_ctrls[index],
- V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- DEFAULT_TAG);
- call_cop(ctx, get_buf_update_val, ctx,
- &ctx->dst_ctrls[index],
- V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
- 0);
- }
-
- vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
- /* decoder dst buffer CFW UNPROT */
- if (ctx->is_drm)
- mfc_raw_unprotect(ctx, dst_mb, index);
-
- mfc_debug(2, "Cleaned up buffer: %d\n", index);
- }
-
- mfc_handle_force_change_status(ctx);
- mfc_debug(2, "After cleanup\n");
-}
-
-static void __mfc_handle_frame_copy_timestamp(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_buf *ref_mb, *src_mb;
- dma_addr_t dec_y_addr;
-
- dec_y_addr = (dma_addr_t)mfc_get_dec_y_addr();
-
- /* Get the source buffer */
- src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (!src_mb) {
- mfc_err_dev("[TS] no src buffers\n");
- return;
- }
-
- ref_mb = mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr);
- if (ref_mb)
- ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp;
-}
-
-static void __mfc_handle_frame_output_move(struct mfc_ctx *ctx,
- dma_addr_t dspl_y_addr, unsigned int released_flag)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_buf *ref_mb;
- int index;
-
- ref_mb = mfc_find_move_buf(&ctx->buf_queue_lock,
- &ctx->dst_buf_queue, &ctx->ref_buf_queue, dspl_y_addr, released_flag);
- if (ref_mb) {
- index = ref_mb->vb.vb2_buf.index;
-
- /* Check if this is the buffer we're looking for */
- mfc_debug(2, "[DPB] Found buf[%d] 0x%08llx, looking for disp addr 0x%08llx\n",
- index, ref_mb->addr[0][0], dspl_y_addr);
-
- if (released_flag & (1 << index)) {
- dec->available_dpb &= ~(1 << index);
- released_flag &= ~(1 << index);
- mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(release)\n",
- mfc_get_warn(mfc_get_int_err()));
- } else {
- dec->err_reuse_flag |= 1 << index;
- mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(not released)\n",
- mfc_get_warn(mfc_get_int_err()));
- }
- dec->dynamic_used |= released_flag;
- }
-}
-
-static void __mfc_handle_frame_output_del(struct mfc_ctx *ctx,
- unsigned int err, unsigned int released_flag)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_raw_info *raw = &ctx->raw_buf;
- struct mfc_buf *ref_mb;
- dma_addr_t dspl_y_addr;
- unsigned int frame_type;
- unsigned int dst_frame_status;
- unsigned int is_video_signal_type = 0, is_colour_description = 0;
- unsigned int is_content_light = 0, is_display_colour = 0;
- unsigned int i, index;
-
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
- is_video_signal_type = mfc_get_video_signal_type();
- is_colour_description = mfc_get_colour_description();
- }
-
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
- is_content_light = mfc_get_sei_avail_content_light();
- is_display_colour = mfc_get_sei_avail_mastering_display();
- }
-
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar)
- __mfc_handle_black_bar_info(dev, ctx);
- else
- dec->black_bar_updated = 0;
-
- if (dec->immediate_display == 1) {
- dspl_y_addr = (dma_addr_t)mfc_get_dec_y_addr();
- frame_type = mfc_get_dec_frame_type();
- } else {
- dspl_y_addr = (dma_addr_t)mfc_get_disp_y_addr();
- frame_type = mfc_get_disp_frame_type();
- }
-
- ref_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
- &ctx->ref_buf_queue, dspl_y_addr);
- if (ref_mb) {
- index = ref_mb->vb.vb2_buf.index;
- /* Check if this is the buffer we're looking for */
- mfc_debug(2, "[BUFINFO][DPB] ctx[%d] get dst index: %d, addr[0]: 0x%08llx\n",
- ctx->num, index, ref_mb->addr[0][0]);
-
- ref_mb->vb.sequence = ctx->sequence;
- ref_mb->vb.field = __mfc_handle_frame_field(ctx);
-
- /* Set reserved2 bits in order to inform SEI information */
- ref_mb->vb.reserved2 = 0;
-
- if (is_content_light) {
- ref_mb->vb.reserved2 |= (1 << 0);
- mfc_debug(2, "[HDR] content light level parsed\n");
- }
-
- if (is_display_colour) {
- ref_mb->vb.reserved2 |= (1 << 1);
- mfc_debug(2, "[HDR] mastering display colour parsed\n");
- }
-
- if (is_video_signal_type) {
- ref_mb->vb.reserved2 |= (1 << 4);
- mfc_debug(2, "[HDR] video signal type parsed\n");
- if (is_colour_description) {
- ref_mb->vb.reserved2 |= (1 << 2);
- mfc_debug(2, "[HDR] matrix coefficients parsed\n");
- ref_mb->vb.reserved2 |= (1 << 3);
- mfc_debug(2, "[HDR] colour description parsed\n");
- }
- }
-
- if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
- if (dec->color_space != MFC_REG_D_COLOR_UNKNOWN) {
- ref_mb->vb.reserved2 |= (1 << 3);
- mfc_debug(2, "[HDR] color space parsed\n");
- }
- ref_mb->vb.reserved2 |= (1 << 4);
- mfc_debug(2, "[HDR] color range parsed\n");
- }
-
- if (dec->black_bar_updated) {
- ref_mb->vb.reserved2 |= (1 << 5);
- mfc_debug(3, "[BLACKBAR] black bar detected\n");
- }
-
- if (ctx->src_fmt->mem_planes == 1) {
- vb2_set_plane_payload(&ref_mb->vb.vb2_buf, 0,
- raw->total_plane_size);
- mfc_debug(5, "single plane payload: %d\n",
- raw->total_plane_size);
- } else {
- for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
- vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i,
- raw->plane_size[i]);
- }
- }
-
- clear_bit(index, &dec->available_dpb);
-
- ref_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
- V4L2_BUF_FLAG_PFRAME |
- V4L2_BUF_FLAG_BFRAME |
- V4L2_BUF_FLAG_ERROR);
-
- switch (frame_type) {
- case MFC_REG_DISPLAY_FRAME_I:
- ref_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
- break;
- case MFC_REG_DISPLAY_FRAME_P:
- ref_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
- break;
- case MFC_REG_DISPLAY_FRAME_B:
- ref_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
- break;
- default:
- break;
- }
-
- if (mfc_get_warn(err)) {
- mfc_err_ctx("Warning for displayed frame: %d\n",
- mfc_get_warn(err));
- ref_mb->vb.flags |= V4L2_BUF_FLAG_ERROR;
- }
-
- if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
- mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
- mfc_handle_released_info(ctx, released_flag, index);
-
- if (dec->immediate_display == 1) {
- dst_frame_status = mfc_get_dec_status();
-
- call_cop(ctx, get_buf_update_val, ctx,
- &ctx->dst_ctrls[index],
- V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
- dst_frame_status);
-
- call_cop(ctx, get_buf_update_val, ctx,
- &ctx->dst_ctrls[index],
- V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- dec->stored_tag);
-
- dec->immediate_display = 0;
- }
-
- /* Update frame tag for packed PB */
- if (CODEC_MULTIFRAME(ctx) && (dec->y_addr_for_pb == dspl_y_addr)) {
- call_cop(ctx, get_buf_update_val, ctx,
- &ctx->dst_ctrls[index],
- V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
- dec->stored_tag);
- dec->y_addr_for_pb = 0;
- }
-
- mfc_qos_update_last_framerate(ctx, ref_mb->vb.vb2_buf.timestamp);
- vb2_buffer_done(&ref_mb->vb.vb2_buf, mfc_get_warn(err) ?
- VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
- }
-}
-
-static void __mfc_handle_frame_new(struct mfc_ctx *ctx, unsigned int err)
-{
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_dev *dev = ctx->dev;
- dma_addr_t dspl_y_addr;
- unsigned int frame_type;
- int mvc_view_id;
- unsigned int prev_flag, released_flag = 0;
-
- frame_type = mfc_get_disp_frame_type();
- mvc_view_id = mfc_get_mvc_disp_view_id();
-
- if (IS_H264_MVC_DEC(ctx)) {
- if (mvc_view_id == 0)
- ctx->sequence++;
- } else {
- ctx->sequence++;
- }
-
- dspl_y_addr = mfc_get_disp_y_addr();
-
- if (dec->immediate_display == 1) {
- dspl_y_addr = (dma_addr_t)mfc_get_dec_y_addr();
- frame_type = mfc_get_dec_frame_type();
- }
-
- mfc_debug(2, "[FRAME] frame type: %d\n", frame_type);
-
- /* If frame is same as previous then skip and do not dequeue */
- if (frame_type == MFC_REG_DISPLAY_FRAME_NOT_CODED)
- if (!CODEC_NOT_CODED(ctx))
- return;
-
- prev_flag = dec->dynamic_used;
- dec->dynamic_used = mfc_get_dec_used_flag();
- released_flag = prev_flag & (~dec->dynamic_used);
-
- mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x, Released buffer = %08x\n",
- prev_flag, dec->dynamic_used, released_flag);
-
- /* decoder dst buffer CFW UNPROT */
- mfc_unprotect_released_dpb(ctx, released_flag);
-
- if ((IS_VC1_RCV_DEC(ctx) &&
- mfc_get_warn(err) == MFC_REG_ERR_SYNC_POINT_NOT_RECEIVED) ||
- (mfc_get_warn(err) == MFC_REG_ERR_BROKEN_LINK))
- __mfc_handle_frame_output_move(ctx, dspl_y_addr, released_flag);
- else
- __mfc_handle_frame_output_del(ctx, err, released_flag);
-}
-
-static void __mfc_handle_frame_error(struct mfc_ctx *ctx,
- unsigned int reason, unsigned int err)
-{
- struct mfc_dec *dec;
- struct mfc_buf *src_mb;
- unsigned int index;
-
- if (ctx->type == MFCINST_ENCODER) {
- mfc_err_ctx("Encoder Interrupt Error: %d\n", err);
- return;
- }
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return;
- }
-
- mfc_err_ctx("Interrupt Error: %d\n", err);
-
- /* Get the source buffer */
- src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-
- if (!src_mb) {
- mfc_err_dev("no src buffers\n");
- } else {
- index = src_mb->vb.vb2_buf.index;
- if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
- mfc_debug(2, "MFC needs next buffer\n");
- dec->consumed = 0;
-
- if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
- /* decoder src buffer CFW UNPROT */
- if (ctx->is_drm)
- mfc_stream_unprotect(ctx, src_mb, index);
-
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- }
-
- mfc_debug(2, "Assesing whether this context should be run again\n");
-}
-
-static void __mfc_handle_ref_frame(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_buf *dst_mb;
- dma_addr_t dec_addr;
-
- dec_addr = (dma_addr_t)mfc_get_dec_y_addr();
-
- /* Try to search decoded address in whole dst queue */
- dst_mb = mfc_find_move_buf_used(&ctx->buf_queue_lock,
- &ctx->ref_buf_queue, &ctx->dst_buf_queue, dec_addr);
- if (dst_mb) {
- mfc_debug(2, "[DPB] Found in dst queue = 0x%08llx, buf = 0x%08llx\n",
- dec_addr, dst_mb->addr[0][0]);
-
- if (!(dec->dynamic_set & mfc_get_dec_used_flag()))
- dec->dynamic_used |= dec->dynamic_set;
- } else {
- mfc_debug(2, "[DPB] Can't find buffer for addr = 0x%08llx\n", dec_addr);
- }
-}
-
-static void __mfc_handle_reuse_buffer(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- unsigned int prev_flag, released_flag = 0;
- int i;
-
- prev_flag = dec->dynamic_used;
- dec->dynamic_used = mfc_get_dec_used_flag();
- released_flag = prev_flag & (~dec->dynamic_used);
-
- if (!released_flag)
- return;
-
- /* Reuse not referenced buf anymore */
- for (i = 0; i < MFC_MAX_DPBS; i++)
- if (released_flag & (1 << i))
- if (mfc_move_reuse_buffer(ctx, i))
- released_flag &= ~(1 << i);
-
- /* Not reused buffer should be released when there is a display frame */
- dec->dec_only_release_flag |= released_flag;
- for (i = 0; i < MFC_MAX_DPBS; i++)
- if (released_flag & (1 << i))
- clear_bit(i, &dec->available_dpb);
-}
-
-static void __mfc_handle_frame_input(struct mfc_ctx *ctx, unsigned int err)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_buf *src_mb;
- unsigned int index;
- int deleted = 0;
- unsigned long consumed;
-
- consumed = dec->consumed + mfc_get_consumed_stream();
-
- if (mfc_get_err(err) == MFC_REG_ERR_NON_PAIRED_FIELD) {
- /*
- * For non-paired field, the same buffer need to be
- * resubmitted and the consumed stream will be 0
- */
- mfc_debug(2, "Not paired field. Running again the same buffer\n");
- return;
- }
-
- /* Get the source buffer */
- src_mb = mfc_get_del_if_consumed(ctx, &ctx->src_buf_queue,
- mfc_get_consumed_stream(), STUFF_BYTE, err, &deleted);
- if (!src_mb) {
- mfc_err_dev("no src buffers\n");
- return;
- }
-
- index = src_mb->vb.vb2_buf.index;
- mfc_debug(2, "[BUFINFO] ctx[%d] get src index: %d, addr: 0x%08llx\n",
- ctx->num, index, src_mb->addr[0][0]);
-
- if (!deleted) {
- /* Run MFC again on the same buffer */
- mfc_debug(2, "[MULTIFRAME] Running again the same buffer\n");
-
- if (CODEC_MULTIFRAME(ctx))
- dec->y_addr_for_pb = (dma_addr_t)mfc_get_dec_y_addr();
-
- dec->consumed = consumed;
- dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused
- - dec->consumed;
- dec->has_multiframe = 1;
-
- MFC_TRACE_CTX("** consumed:%ld, remained:%ld, addr:0x%08llx\n",
- dec->consumed, dec->remained_size, dec->y_addr_for_pb);
- /* Do not move src buffer to done_list */
- return;
- }
-
- if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
- dec->consumed = 0;
- dec->remained_size = 0;
-
- if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
- /* decoder src buffer CFW UNPROT */
- if (ctx->is_drm)
- mfc_stream_unprotect(ctx, src_mb, index);
-
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-}
-
-/* Handle frame decoding interrupt */
-static void __mfc_handle_frame(struct mfc_ctx *ctx,
- unsigned int reason, unsigned int err)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- unsigned int dst_frame_status, sei_avail_frame_pack;
- unsigned int res_change, need_dpb_change, need_scratch_change;
-
- dst_frame_status = mfc_get_disp_status();
- res_change = mfc_get_res_change();
- need_dpb_change = mfc_get_dpb_change();
- need_scratch_change = mfc_get_scratch_change();
- sei_avail_frame_pack = mfc_get_sei_avail_frame_pack();
-
- if (dec->immediate_display == 1)
- dst_frame_status = mfc_get_dec_status();
-
- mfc_debug(2, "[FRAME] frame status: %d\n", dst_frame_status);
- mfc_debug(2, "[FRAME] display status: %d, type: %d, yaddr: %#x\n",
- mfc_get_disp_status(), mfc_get_disp_frame_type(),
- mfc_get_disp_y_addr());
- mfc_debug(2, "[FRAME] decoded status: %d, type: %d, yaddr: %#x\n",
- mfc_get_dec_status(), mfc_get_dec_frame_type(),
- mfc_get_dec_y_addr());
-
- mfc_debug(4, "[HDR] SEI available status: 0x%08x\n", mfc_get_sei_avail());
- mfc_debug(4, "[HDR] SEI content light: 0x%08x\n", mfc_get_sei_content_light());
- mfc_debug(4, "[HDR] SEI luminance: 0x%08x, 0x%08x white point: 0x%08x\n",
- mfc_get_sei_mastering0(), mfc_get_sei_mastering1(),
- mfc_get_sei_mastering2());
- mfc_debug(4, "[HDR] SEI display primaries: 0x%08x, 0x%08x, 0x%08x\n",
- mfc_get_sei_mastering3(), mfc_get_sei_mastering4(),
- mfc_get_sei_mastering5());
- mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x\n",
- dec->dynamic_used, mfc_get_dec_used_flag());
-
- if (ctx->state == MFCINST_RES_CHANGE_INIT)
- mfc_change_state(ctx, MFCINST_RES_CHANGE_FLUSH);
-
- if (res_change) {
- mfc_debug(2, "[DRC] Resolution change set to %d\n", res_change);
- mfc_change_state(ctx, MFCINST_RES_CHANGE_INIT);
- ctx->wait_state = WAIT_DECODING;
- mfc_debug(7, "[DRC] Decoding waiting! : %d\n", ctx->wait_state);
- return;
- }
-
- if (need_dpb_change || need_scratch_change)
- mfc_debug(2, "[DRC] Interframe resolution change is not supported\n");
-
- if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0) &&
- mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
- mfc_err_dev("Queue count is zero for src and dst\n");
- goto leave_handle_frame;
- }
-
- if (IS_H264_DEC(ctx) && sei_avail_frame_pack &&
- dst_frame_status == MFC_REG_DEC_STATUS_DECODING_ONLY) {
- mfc_debug(2, "Frame packing SEI exists for a frame\n");
- mfc_debug(2, "Reallocate DPBs and issue init_buffer\n");
- ctx->is_dpb_realloc = 1;
- mfc_change_state(ctx, MFCINST_HEAD_PARSED);
- ctx->capture_state = QUEUE_FREE;
- ctx->wait_state = WAIT_DECODING;
- __mfc_handle_frame_all_extracted(ctx);
- goto leave_handle_frame;
- }
-
- /* All frames remaining in the buffer have been extracted */
- if (dst_frame_status == MFC_REG_DEC_STATUS_DECODING_EMPTY) {
- if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
- struct mfc_timestamp *temp_ts = NULL;
-
- mfc_debug(2, "[DRC] Last frame received after resolution change\n");
- __mfc_handle_frame_all_extracted(ctx);
- mfc_change_state(ctx, MFCINST_RES_CHANGE_END);
- /* If there is no display frame after resolution change,
- * Some released frames can't be unprotected.
- * So, check and request unprotection in the end of DRC.
- */
- mfc_cleanup_assigned_dpb(ctx);
-
- /* empty the timestamp queue */
- while (!list_empty(&ctx->ts_list)) {
- temp_ts = list_entry((&ctx->ts_list)->next,
- struct mfc_timestamp, list);
- list_del(&temp_ts->list);
- }
- ctx->ts_count = 0;
- ctx->ts_is_full = 0;
- mfc_qos_reset_last_framerate(ctx);
- mfc_qos_set_framerate(ctx, DEC_DEFAULT_FPS);
-
- goto leave_handle_frame;
- } else {
- __mfc_handle_frame_all_extracted(ctx);
- }
- }
-
- if (mfc_get_num_of_tile() >= 4)
- dec->num_of_tile_over_4 = 1;
-
- switch (dst_frame_status) {
- case MFC_REG_DEC_STATUS_DECODING_DISPLAY:
- __mfc_handle_ref_frame(ctx);
- break;
- case MFC_REG_DEC_STATUS_DECODING_ONLY:
- __mfc_handle_ref_frame(ctx);
- /*
- * Some cases can have many decoding only frames like VP9
- * alt-ref frame. So need handling release buffer
- * because of DPB full.
- */
- __mfc_handle_reuse_buffer(ctx);
- break;
- default:
- break;
- }
-
- if (mfc_dec_status_decoding(dst_frame_status))
- __mfc_handle_frame_copy_timestamp(ctx);
-
- /* A frame has been decoded and is in the buffer */
- if (mfc_dec_status_display(dst_frame_status))
- __mfc_handle_frame_new(ctx, err);
- else
- mfc_debug(2, "No frame decode\n");
-
- /* Mark source buffer as complete */
- if (dst_frame_status != MFC_REG_DEC_STATUS_DISPLAY_ONLY)
- __mfc_handle_frame_input(ctx, err);
-
-leave_handle_frame:
- mfc_debug(2, "Assesing whether this context should be run again\n");
-}
-
-static void __mfc_handle_stream_copy_timestamp(struct mfc_ctx *ctx, struct mfc_buf *src_mb)
-{
- struct mfc_dev *dev;
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_enc_params *p = &enc->params;
- struct mfc_buf *dst_mb;
- u32 interval;
- u64 start_timestamp;
- u64 new_timestamp;
-
- if (!ctx) {
- mfc_err_dev("[BUFCON][TS] no mfc context to run\n");
- return;
- }
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("[BUFCON][TS] no device to run\n");
- return;
- }
-
- start_timestamp = src_mb->vb.vb2_buf.timestamp;
- interval = NSEC_PER_SEC / p->rc_framerate;
- if (debug_ts == 1)
- mfc_info_ctx("[BUFCON][TS] %dfps, start timestamp: %lld, base interval: %d\n",
- p->rc_framerate, start_timestamp, interval);
-
- new_timestamp = start_timestamp + (interval * src_mb->done_index);
- if (debug_ts == 1)
- mfc_info_ctx("[BUFCON][TS] new timestamp: %lld, interval: %d\n",
- new_timestamp, interval * src_mb->done_index);
-
- /* Get the destination buffer */
- dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (dst_mb)
- dst_mb->vb.vb2_buf.timestamp = new_timestamp;
-}
-
-static void __mfc_handle_stream_input(struct mfc_ctx *ctx)
-{
- struct mfc_raw_info *raw;
- struct mfc_buf *ref_mb, *src_mb;
- dma_addr_t enc_addr[3] = { 0, 0, 0 };
- int i, found_in_src_queue = 0;
- unsigned int index;
-
- raw = &ctx->raw_buf;
-
- mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
- if (enc_addr[0] == 0) {
- mfc_debug(3, "no encoded src\n");
- goto move_buf;
- }
- for (i = 0; i < raw->num_planes; i++)
- mfc_debug(2, "[BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
- ctx->num, i, enc_addr[i]);
-
- if (IS_BUFFER_BATCH_MODE(ctx)) {
- src_mb = mfc_find_first_buf(&ctx->buf_queue_lock,
- &ctx->src_buf_queue, enc_addr[0]);
- if (src_mb) {
- found_in_src_queue = 1;
-
- __mfc_handle_stream_copy_timestamp(ctx, src_mb);
- src_mb->done_index++;
- mfc_debug(4, "[BUFCON] batch buf done_index: %d\n", src_mb->done_index);
-
- index = src_mb->vb.vb2_buf.index;
-
- if (call_cop(ctx, recover_buf_ctrls_val, ctx,
- &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
- /* single buffer || last image in a buffer container */
- if (!src_mb->num_valid_bufs || src_mb->done_index == src_mb->num_valid_bufs) {
- src_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
- &ctx->src_buf_queue, enc_addr[0]);
- for (i = 0; i < raw->num_planes; i++)
- mfc_bufcon_put_daddr(ctx, src_mb, i);
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
- }
-
- /* encoder src buffer CFW UNPROT */
- if (ctx->is_drm)
- mfc_raw_unprotect(ctx, src_mb, index);
- }
- } else {
- /* normal single buffer */
- src_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
- &ctx->src_buf_queue, enc_addr[0]);
- if (src_mb) {
- found_in_src_queue = 1;
- index = src_mb->vb.vb2_buf.index;
- if (call_cop(ctx, recover_buf_ctrls_val, ctx,
- &ctx->src_ctrls[index]) < 0)
- mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
- mfc_debug(3, "find src buf in src_queue\n");
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
- /* encoder src buffer CFW UNPROT */
- if (ctx->is_drm)
- mfc_raw_unprotect(ctx, src_mb, index);
- } else {
- mfc_debug(3, "no src buf in src_queue\n");
- ref_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
- &ctx->ref_buf_queue, enc_addr[0]);
- if (ref_mb) {
- mfc_debug(3, "find src buf in ref_queue\n");
- vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
- /* encoder src buffer CFW UNPROT */
- if (ctx->is_drm) {
- index = ref_mb->vb.vb2_buf.index;
- mfc_raw_unprotect(ctx, ref_mb, index);
- }
- } else {
- mfc_err_ctx("couldn't find src buffer\n");
- }
- }
- }
-
-move_buf:
- /* move enqueued src buffer: src queue -> ref queue */
- if (!found_in_src_queue && ctx->state != MFCINST_FINISHING) {
- mfc_move_first_buf_used(&ctx->buf_queue_lock,
- &ctx->ref_buf_queue, &ctx->src_buf_queue, MFC_QUEUE_ADD_BOTTOM);
-
- mfc_debug(2, "enc src_buf_queue(%d) -> ref_buf_queue(%d)\n",
- mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
- mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
- }
-}
-
-static void __mfc_handle_stream_output(struct mfc_ctx *ctx, int slice_type,
- unsigned int strm_size)
-{
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_buf *dst_mb;
- unsigned int index;
-
- if (strm_size == 0) {
- mfc_debug(3, "no encoded dst (reuse)\n");
- return;
- } else if (strm_size < 0) {
- mfc_err_ctx("invalid stream size: %d\n", strm_size);
- return;
- }
-
- /* at least one more dest. buffers exist always */
- dst_mb = mfc_get_del_buf(&ctx->buf_queue_lock,
- &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (!dst_mb) {
- mfc_err_ctx("no dst buffers\n");
- return;
- }
-
- mfc_debug(2, "[BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
- ctx->num, dst_mb->addr[0][0]);
-
- dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
- V4L2_BUF_FLAG_PFRAME |
- V4L2_BUF_FLAG_BFRAME);
- switch (slice_type) {
- case MFC_REG_E_SLICE_TYPE_I:
- dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
- break;
- case MFC_REG_E_SLICE_TYPE_P:
- dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
- break;
- case MFC_REG_E_SLICE_TYPE_B:
- dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
- break;
- default:
- dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
- break;
- }
- mfc_debug(2, "[STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
-
- if (IS_BPG_ENC(ctx)) {
- strm_size += enc->header_size;
- mfc_debug(2, "bpg total stream size: %d\n", strm_size);
- }
- vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
-
- index = dst_mb->vb.vb2_buf.index;
- if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
- mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
- vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
- /* encoder dst buffer CFW UNPROT */
- if (ctx->is_drm)
- mfc_stream_unprotect(ctx, dst_mb, index);
-}
-
-/* Handle frame encoding interrupt */
-static int __mfc_handle_stream(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- int slice_type;
- unsigned int strm_size;
- unsigned int pic_count;
-
- slice_type = mfc_get_enc_slice_type();
- strm_size = mfc_get_enc_strm_size();
- pic_count = mfc_get_enc_pic_count();
-
- mfc_debug(2, "[STREAM] encoded slice type: %d, size: %d, display order: %d\n",
- slice_type, strm_size, pic_count);
-
- /* buffer full handling */
- if (enc->buf_full) {
- mfc_change_state(ctx, MFCINST_ABORT_INST);
- return 0;
- }
- if (ctx->state == MFCINST_RUNNING_BUF_FULL)
- mfc_change_state(ctx, MFCINST_RUNNING);
-
- /* set encoded frame type */
- enc->frame_type = slice_type;
- ctx->sequence++;
-
- if (enc->in_slice) {
- if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
- mfc_clear_bit(ctx->num, &dev->work_bits);
- }
- return 0;
- }
-
- /* handle source buffer */
- __mfc_handle_stream_input(ctx);
-
- /* handle destination buffer */
- __mfc_handle_stream_output(ctx, slice_type, strm_size);
-
- return 0;
-}
-
-/* Error handling for interrupt */
-static inline void __mfc_handle_error(struct mfc_ctx *ctx,
- unsigned int reason, unsigned int err)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_buf *src_mb;
- int index;
-
- mfc_err_ctx("Interrupt Error: display: %d, decoded: %d\n",
- mfc_get_warn(err), mfc_get_err(err));
- err = mfc_get_err(err);
-
- /* Error recovery is dependent on the state of context */
- switch (ctx->state) {
- case MFCINST_RES_CHANGE_END:
- case MFCINST_GOT_INST:
- /* This error had to happen while parsing the header */
- if (!ctx->is_drm) {
- unsigned char *stream_vir = NULL;
- unsigned int strm_size = 0;
-
- src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (src_mb) {
- stream_vir = src_mb->vir_addr;
- strm_size = src_mb->vb.vb2_buf.planes[0].bytesused;
- if (strm_size > 32)
- strm_size = 32;
-
- if (stream_vir && strm_size)
- print_hex_dump(KERN_ERR, "No header: ",
- DUMP_PREFIX_ADDRESS, strm_size, 0,
- stream_vir, strm_size, false);
-
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
- }
- } else {
- src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (src_mb) {
- index = src_mb->vb.vb2_buf.index;
- /* decoder src buffer CFW UNPROT */
- mfc_stream_unprotect(ctx, src_mb, index);
- vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
- }
- }
- break;
- case MFCINST_INIT:
- /* This error had to happen while acquireing instance */
- case MFCINST_RETURN_INST:
- /* This error had to happen while releasing instance */
- case MFCINST_DPB_FLUSHING:
- /* This error had to happen while flushing DPB */
- case MFCINST_SPECIAL_PARSING:
- case MFCINST_SPECIAL_PARSING_NAL:
- /* This error had to happen while special parsing */
- break;
- case MFCINST_HEAD_PARSED:
- /* This error had to happen while setting dst buffers */
- case MFCINST_RES_CHANGE_INIT:
- case MFCINST_RES_CHANGE_FLUSH:
- /* This error has to happen while resolution change */
- case MFCINST_ABORT_INST:
- /* This error has to happen while buffer full handling */
- case MFCINST_FINISHING:
- /* It is higly probable that an error occured
- * while decoding a frame */
- mfc_change_state(ctx, MFCINST_ERROR);
- /* Mark all dst buffers as having an error */
- mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
- /* Mark all src buffers as having an error */
- mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_queue);
- break;
- default:
- mfc_err_ctx("Encountered an error interrupt which had not been handled\n");
- mfc_err_ctx("ctx->state = %d, ctx->inst_no = %d\n",
- ctx->state, ctx->inst_no);
- break;
- }
-
- mfc_wake_up_dev(dev, reason, err);
-
- return;
-}
-
-/* Handle header decoder interrupt */
-static int __mfc_handle_seq_dec(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- int i, is_interlace, is_mbaff;
-
- if (ctx->src_fmt->fourcc != V4L2_PIX_FMT_FIMV1) {
- ctx->img_width = mfc_get_img_width();
- ctx->img_height = mfc_get_img_height();
- ctx->crop_width = ctx->img_width;
- ctx->crop_height = ctx->img_height;
- mfc_info_ctx("[STREAM] resolution w: %d, h: %d\n", ctx->img_width, ctx->img_height);
- }
-
- ctx->dpb_count = mfc_get_dpb_count();
- ctx->scratch_buf_size = mfc_get_scratch_size();
- for (i = 0; i < ctx->dst_fmt->num_planes; i++)
- ctx->min_dpb_size[i] = mfc_get_min_dpb_size(i);
-
- mfc_dec_store_crop_info(ctx);
- dec->mv_count = mfc_get_mv_count();
- if (CODEC_10BIT(ctx) && dev->pdata->support_10bit) {
- if (mfc_get_luma_bit_depth_minus8() ||
- mfc_get_chroma_bit_depth_minus8() ||
- mfc_get_profile() == MFC_REG_D_PROFILE_HEVC_MAIN_10) {
- ctx->is_10bit = 1;
- mfc_info_ctx("[STREAM][10BIT] 10bit contents, profile: %d, depth: %d/%d\n",
- mfc_get_profile(),
- mfc_get_luma_bit_depth_minus8() + 8,
- mfc_get_chroma_bit_depth_minus8() + 8);
- }
- }
- if (CODEC_422FORMAT(ctx) && dev->pdata->support_422) {
- if (mfc_get_chroma_format() == MFC_REG_D_CHROMA_422) {
- ctx->is_422 = 1;
- mfc_info_ctx("[STREAM] 422 chroma format\n");
- }
- }
-
- if (ctx->img_width == 0 || ctx->img_height == 0)
- mfc_change_state(ctx, MFCINST_ERROR);
- else
- mfc_change_state(ctx, MFCINST_HEAD_PARSED);
-
- if (ctx->state == MFCINST_HEAD_PARSED) {
- is_interlace = mfc_is_interlace_picture();
- is_mbaff = mfc_is_mbaff_picture();
- if (is_interlace || is_mbaff)
- dec->is_interlaced = 1;
- mfc_debug(2, "[INTERLACE] interlace: %d, mbaff: %d\n", is_interlace, is_mbaff);
- }
-
- if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx)) {
- struct mfc_buf *src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (src_mb) {
- dec->consumed += mfc_get_consumed_stream();
- mfc_debug(2, "[STREAM] header total size : %d, consumed : %lu\n",
- src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed);
- if ((dec->consumed > 0) &&
- (src_mb->vb.vb2_buf.planes[0].bytesused > dec->consumed)) {
- dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused -
- dec->consumed;
- mfc_debug(2, "[STREAM] there is remained bytes(%lu) after header parsing\n",
- dec->remained_size);
- } else {
- dec->consumed = 0;
- dec->remained_size = 0;
- }
- }
- }
-
- if (IS_VP9_DEC(ctx)) {
- dec->color_range = mfc_get_color_range();
- dec->color_space = mfc_get_color_space();
- mfc_debug(2, "color range: %d, color space: %d, It's valid for VP9\n",
- dec->color_range, dec->color_space);
- }
-
- return 0;
-}
-
-/* Handle header encoder interrupt */
-static int __mfc_handle_seq_enc(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- struct mfc_enc_params *p = &enc->params;
- struct mfc_buf *dst_mb;
- int ret;
-
- enc->header_size = mfc_get_enc_strm_size();
- mfc_debug(2, "[STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
- mfc_get_enc_slice_type(), enc->header_size,
- mfc_get_enc_pic_count());
-
- if (IS_BPG_ENC(ctx)) {
- dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (!dst_mb) {
- mfc_err_dev("no dst buffers\n");
- return -EAGAIN;
- }
-
- dst_mb->vb.vb2_buf.planes[0].data_offset += (enc->header_size +
- p->codec.bpg.thumb_size + p->codec.bpg.exif_size);
- mfc_debug(2, "offset for NAL_START: %d (header: %d + thumb: %d + exif: %d)\n",
- dst_mb->vb.vb2_buf.planes[0].data_offset,
- enc->header_size,
- p->codec.bpg.thumb_size,
- p->codec.bpg.exif_size);
- } else {
- if ((p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) ||
- (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY)) {
- dst_mb = mfc_get_del_buf(&ctx->buf_queue_lock,
- &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
- if (!dst_mb) {
- mfc_err_dev("no dst buffers\n");
- return -EAGAIN;
- }
-
- vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, mfc_get_enc_strm_size());
- vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
- /* encoder dst buffer CFW UNPROT */
- if (ctx->is_drm) {
- int index = dst_mb->vb.vb2_buf.index;
-
- mfc_stream_unprotect(ctx, dst_mb, index);
- }
- }
- }
-
- ctx->dpb_count = mfc_get_enc_dpb_count();
- ctx->scratch_buf_size = mfc_get_enc_scratch_size();
-
- /* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */
- mfc_clear_roi_enable(dev);
-
- if (!ctx->codec_buffer_allocated) {
- mfc_debug(2, "[DRC] previous codec buffer is exist\n");
-
- if (dev->has_mmcache && dev->mmcache.is_on_status)
- mfc_invalidate_mmcache(dev);
-
- mfc_release_codec_buffers(ctx);
- }
- ret = mfc_alloc_codec_buffers(ctx);
- if (ret) {
- mfc_err_ctx("Failed to allocate encoding buffers\n");
- return ret;
- }
-
- mfc_change_state(ctx, MFCINST_HEAD_PARSED);
-
- return 0;
-}
-
-static inline int is_err_condition(unsigned int err)
-{
- if (err == MFC_REG_ERR_NO_AVAILABLE_DPB ||
- err == MFC_REG_ERR_INSUFFICIENT_DPB_SIZE ||
- err == MFC_REG_ERR_INSUFFICIENT_NUM_DPB ||
- err == MFC_REG_ERR_INSUFFICIENT_MV_BUF_SIZE ||
- err == MFC_REG_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE)
- return 1;
-
- return 0;
-}
-
-irqreturn_t mfc_top_half_irq(int irq, void *priv)
-{
- struct mfc_dev *dev = priv;
- struct mfc_ctx *ctx;
- unsigned int err;
- unsigned int reason;
-
- ctx = dev->ctx[dev->curr_ctx];
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return IRQ_WAKE_THREAD;
- }
-
- reason = mfc_get_int_reason();
- err = mfc_get_int_err();
- mfc_debug(2, "[c:%d] Int reason: %d (err: %d)\n",
- dev->curr_ctx, reason, err);
- MFC_TRACE_CTX("<< INT(top): %d\n", reason);
-
- mfc_perf_measure_off(dev);
-
- return IRQ_WAKE_THREAD;
-}
-
-/*
- * Return value description
- * 0: NAL-Q is handled successfully
- * 1: NAL_START command
- * -1: Error
-*/
-static inline int __mfc_nal_q_irq(struct mfc_dev *dev,
- unsigned int reason, unsigned int err)
-{
- int ret = -1;
- unsigned int errcode;
-
- nal_queue_handle *nal_q_handle = dev->nal_q_handle;
- EncoderOutputStr *pOutStr;
-
- switch (reason) {
- case MFC_REG_R2H_CMD_QUEUE_DONE_RET:
- pOutStr = mfc_nal_q_dequeue_out_buf(dev,
- nal_q_handle->nal_q_out_handle, &errcode);
- if (pOutStr) {
- if (mfc_nal_q_handle_out_buf(dev, pOutStr))
- mfc_err_dev("[NALQ] Failed to handle out buf\n");
- } else {
- mfc_err_dev("[NALQ] pOutStr is NULL\n");
- }
-
- if (nal_q_handle->nal_q_exception)
- mfc_set_bit(nal_q_handle->nal_q_out_handle->nal_q_ctx,
- &dev->work_bits);
- mfc_clear_int_sfr();
-
- if (!nal_q_handle->nal_q_exception)
- mfc_nal_q_clock_off(dev, nal_q_handle);
-
- ret = 0;
- break;
- case MFC_REG_R2H_CMD_COMPLETE_QUEUE_RET:
- mfc_watchdog_stop_tick(dev);
- nal_q_handle->nal_q_state = NAL_Q_STATE_CREATED;
- MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
- mfc_debug(2, "[NALQ] return to created state\n");
- mfc_nal_q_cleanup_queue(dev);
- mfc_nal_q_cleanup_clock(dev);
- mfc_clear_int_sfr();
- mfc_pm_clock_off(dev);
- mfc_wake_up_dev(dev, reason, err);
-
- ret = 0;
- break;
- default:
- if (nal_q_handle->nal_q_state == NAL_Q_STATE_STARTED ||
- nal_q_handle->nal_q_state == NAL_Q_STATE_STOPPED) {
- mfc_err_dev("[NALQ] Should not be here! state: %d, int reason : %d\n",
- nal_q_handle->nal_q_state, reason);
- mfc_clear_int_sfr();
-
- ret = -1;
- } else {
- /* NAL START */
- ret = 1;
- }
-
- break;
- }
-
- if (ret == 0)
- queue_work(dev->butler_wq, &dev->butler_work);
-
- return ret;
-}
-
-static inline int __mfc_handle_done_frame(struct mfc_ctx *ctx,
- unsigned int reason, unsigned int err)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = NULL;
-
- if (ctx->type == MFCINST_DECODER) {
- if (ctx->state == MFCINST_SPECIAL_PARSING_NAL) {
- mfc_clear_int_sfr();
- mfc_pm_clock_off(dev);
- mfc_clear_bit(ctx->num, &dev->work_bits);
- mfc_change_state(ctx, MFCINST_RUNNING);
- mfc_wake_up_ctx(ctx, reason, err);
- return 0;
- }
- __mfc_handle_frame(ctx, reason, err);
- } else if (ctx->type == MFCINST_ENCODER) {
- if (ctx->otf_handle) {
- mfc_otf_handle_stream(ctx);
- return 1;
- }
- enc = ctx->enc_priv;
- if (reason == MFC_REG_R2H_CMD_SLICE_DONE_RET) {
- dev->preempt_ctx = ctx->num;
- enc->buf_full = 0;
- enc->in_slice = 1;
- } else if (reason == MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET) {
- mfc_err_ctx("stream buffer size(%d) isn't enough\n",
- mfc_get_enc_strm_size());
- dev->preempt_ctx = ctx->num;
- enc->buf_full = 1;
- enc->in_slice = 0;
- } else {
- enc->buf_full = 0;
- enc->in_slice = 0;
- }
- __mfc_handle_stream(ctx);
- }
-
- return 1;
-}
-
-static inline void __mfc_handle_nal_abort(struct mfc_ctx *ctx)
-{
- struct mfc_enc *enc = ctx->enc_priv;
-
- if (ctx->type == MFCINST_ENCODER) {
- mfc_change_state(ctx, MFCINST_RUNNING_BUF_FULL);
- enc->buf_full = 0;
- if (IS_VP8_ENC(ctx))
- mfc_err_ctx("stream buffer size isn't enough\n");
- __mfc_handle_stream(ctx);
- } else {
- mfc_change_state(ctx, MFCINST_ABORT);
- }
-}
-
-static int __mfc_irq_dev(struct mfc_dev *dev, unsigned int reason, unsigned int err)
-{
- /* Stop the timeout watchdog */
- if (reason != MFC_REG_R2H_CMD_FW_STATUS_RET)
- mfc_watchdog_stop_tick(dev);
-
- switch (reason) {
- case MFC_REG_R2H_CMD_CACHE_FLUSH_RET:
- case MFC_REG_R2H_CMD_SYS_INIT_RET:
- case MFC_REG_R2H_CMD_FW_STATUS_RET:
- case MFC_REG_R2H_CMD_SLEEP_RET:
- case MFC_REG_R2H_CMD_WAKEUP_RET:
- mfc_clear_int_sfr();
- mfc_wake_up_dev(dev, reason, err);
- return 0;
- }
-
- return 1;
-}
-
-static int __mfc_irq_ctx(struct mfc_ctx *ctx, unsigned int reason, unsigned int err)
-{
- struct mfc_dev *dev = ctx->dev;
-
- switch (reason) {
- case MFC_REG_R2H_CMD_ERR_RET:
- if (ctx->otf_handle) {
- mfc_otf_handle_error(ctx, reason, err);
- break;
- }
- /* An error has occured */
- if (ctx->state == MFCINST_RUNNING || ctx->state == MFCINST_ABORT) {
- if ((mfc_get_err(err) >= MFC_REG_ERR_WARNINGS_START) &&
- (mfc_get_err(err) <= MFC_REG_ERR_WARNINGS_END))
- __mfc_handle_frame(ctx, reason, err);
- else
- __mfc_handle_frame_error(ctx, reason, err);
- } else {
- __mfc_handle_error(ctx, reason, err);
- }
- break;
- case MFC_REG_R2H_CMD_SLICE_DONE_RET:
- case MFC_REG_R2H_CMD_FIELD_DONE_RET:
- case MFC_REG_R2H_CMD_FRAME_DONE_RET:
- case MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET:
- return __mfc_handle_done_frame(ctx, reason, err);
- case MFC_REG_R2H_CMD_COMPLETE_SEQ_RET:
- if (ctx->type == MFCINST_ENCODER) {
- __mfc_handle_stream(ctx);
- mfc_change_state(ctx, MFCINST_RUNNING);
- } else if (ctx->type == MFCINST_DECODER) {
- return __mfc_handle_done_frame(ctx, reason, err);
- }
- break;
- case MFC_REG_R2H_CMD_SEQ_DONE_RET:
- if (ctx->type == MFCINST_ENCODER) {
- if (ctx->otf_handle) {
- mfc_otf_handle_seq(ctx);
- break;
- }
- __mfc_handle_seq_enc(ctx);
- } else if (ctx->type == MFCINST_DECODER) {
- __mfc_handle_seq_dec(ctx);
- }
- break;
- case MFC_REG_R2H_CMD_OPEN_INSTANCE_RET:
- ctx->inst_no = mfc_get_inst_no();
- mfc_change_state(ctx, MFCINST_GOT_INST);
- break;
- case MFC_REG_R2H_CMD_CLOSE_INSTANCE_RET:
- mfc_change_state(ctx, MFCINST_FREE);
- break;
- case MFC_REG_R2H_CMD_NAL_ABORT_RET:
- __mfc_handle_nal_abort(ctx);
- break;
- case MFC_REG_R2H_CMD_DPB_FLUSH_RET:
- mfc_change_state(ctx, MFCINST_ABORT);
- break;
- case MFC_REG_R2H_CMD_INIT_BUFFERS_RET:
- if (err != 0) {
- mfc_err_ctx("INIT_BUFFERS_RET error: %d\n", err);
- break;
- }
-
- mfc_change_state(ctx, MFCINST_RUNNING);
- if (ctx->type == MFCINST_DECODER) {
- if (ctx->wait_state == WAIT_DECODING) {
- ctx->wait_state = WAIT_INITBUF_DONE;
- mfc_debug(2, "INIT_BUFFER has done, but can't start decoding\n");
- }
- if (ctx->is_dpb_realloc)
- ctx->is_dpb_realloc = 0;
- }
- break;
- default:
- mfc_err_ctx("Unknown int reason: %d\n", reason);
- }
-
- return 1;
-}
-
-/* Interrupt processing */
-irqreturn_t mfc_irq(int irq, void *priv)
-{
- struct mfc_dev *dev = priv;
- struct mfc_ctx *ctx;
- unsigned int reason;
- unsigned int err;
- int ret = -1;
-
- mfc_debug_enter();
-
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- goto irq_end;
- }
-
- if (mfc_pm_get_pwr_ref_cnt(dev) == 0) {
- mfc_err_dev("no mfc power on\n");
- call_dop(dev, dump_and_stop_debug_mode, dev);
- goto irq_end;
- }
-
- /* Get the reason of interrupt and the error code */
- reason = mfc_get_int_reason();
- err = mfc_get_int_err();
- mfc_debug(1, "Int reason: %d (err: %d)\n", reason, err);
- MFC_TRACE_DEV("<< INT: %d\n", reason);
-
- dev->preempt_ctx = MFC_NO_INSTANCE_SET;
-
- if (dbg_enable && (reason != MFC_REG_R2H_CMD_QUEUE_DONE_RET))
- mfc_dbg_disable(dev);
-
- if ((sfr_dump & MFC_DUMP_ERR_INT) && (reason == MFC_REG_R2H_CMD_ERR_RET))
- call_dop(dev, dump_regs, dev);
-
- if ((sfr_dump & MFC_DUMP_WARN_INT) &&
- (err && (reason != MFC_REG_R2H_CMD_ERR_RET)))
- call_dop(dev, dump_regs, dev);
-
- if (is_err_condition(err))
- call_dop(dev, dump_and_stop_debug_mode, dev);
-
- if (dev->nal_q_handle) {
- ret = __mfc_nal_q_irq(dev, reason, err);
- if (ret == 0) {
- mfc_debug(2, "[NALQ] command was handled\n");
- goto irq_end;
- } else if (ret == 1){
- /* Path through */
- mfc_debug(2, "NAL_START command will be handled\n");
- } else {
- mfc_debug(2, "[NALQ] command handling Error\n");
- goto irq_end;
- }
- }
-
- ret = __mfc_irq_dev(dev, reason, err);
- if (!ret)
- goto irq_end;
-
- ctx = dev->ctx[dev->curr_ctx];
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- mfc_clear_int_sfr();
- mfc_pm_clock_off(dev);
- goto irq_end;
- }
-
- ret = __mfc_irq_ctx(ctx, reason, err);
- if (!ret)
- goto irq_end;
-
- /* clean-up interrupt */
- mfc_clear_int_sfr();
-
- if ((ctx->state != MFCINST_RES_CHANGE_INIT) && (mfc_ctx_ready(ctx) == 0))
- mfc_clear_bit(ctx->num, &dev->work_bits);
-
- if (ctx->otf_handle) {
- if (mfc_otf_ctx_ready(ctx))
- mfc_set_bit(ctx->num, &dev->work_bits);
- else
- mfc_clear_bit(ctx->num, &dev->work_bits);
- }
-
- mfc_hwlock_handler_irq(dev, ctx, reason, err);
-
-irq_end:
- mfc_debug_leave();
- return IRQ_HANDLED;
-}
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_irq.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MFC_IRQ_H
-#define __MFC_IRQ_H __FILE__
-
-#include <linux/interrupt.h>
-
-#include "mfc_common.h"
-
-#include "mfc_utils.h"
-
-irqreturn_t mfc_top_half_irq(int irq, void *priv);
-irqreturn_t mfc_irq(int irq, void *priv);
-
-static inline void mfc_handle_force_change_status(struct mfc_ctx *ctx)
-{
- if (ctx->state != MFCINST_ABORT && ctx->state != MFCINST_HEAD_PARSED &&
- ctx->state != MFCINST_RES_CHANGE_FLUSH)
- mfc_change_state(ctx, MFCINST_RUNNING);
-}
-
-#endif /* __MFC_IRQ_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_isr.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_isr.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_otf.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_pm.h"
+#include "mfc_perf_measure.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
+#include "mfc_mmcache.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static void __mfc_handle_black_bar_info(struct mfc_dev *dev, struct mfc_ctx *ctx)
+{
+ struct v4l2_rect new_black_bar;
+ int black_bar_info;
+ struct mfc_dec *dec = ctx->dec_priv;
+
+ black_bar_info = mfc_get_black_bar_detection();
+ mfc_debug(3, "[BLACKBAR] type: %#x\n", black_bar_info);
+
+ if (black_bar_info == MFC_REG_DISP_STATUS_BLACK_BAR) {
+ new_black_bar.left = mfc_get_black_bar_pos_x();
+ new_black_bar.top = mfc_get_black_bar_pos_y();
+ new_black_bar.width = mfc_get_black_bar_image_w();
+ new_black_bar.height = mfc_get_black_bar_image_h();
+ } else if (black_bar_info == MFC_REG_DISP_STATUS_BLACK_SCREEN) {
+ new_black_bar.left = -1;
+ new_black_bar.top = -1;
+ new_black_bar.width = ctx->img_width;
+ new_black_bar.height = ctx->img_height;
+ } else if (black_bar_info == MFC_REG_DISP_STATUS_NOT_DETECTED) {
+ new_black_bar.left = 0;
+ new_black_bar.top = 0;
+ new_black_bar.width = ctx->img_width;
+ new_black_bar.height = ctx->img_height;
+ } else {
+ mfc_err_ctx("[BLACKBAR] Not supported type: %#x\n", black_bar_info);
+ dec->black_bar_updated = 0;
+ return;
+ }
+
+ if ((new_black_bar.left == dec->black_bar.left) &&
+ (new_black_bar.top == dec->black_bar.top) &&
+ (new_black_bar.width == dec->black_bar.width) &&
+ (new_black_bar.height == dec->black_bar.height)) {
+ mfc_debug(4, "[BLACKBAR] information was not changed\n");
+ dec->black_bar_updated = 0;
+ return;
+ }
+
+ dec->black_bar = new_black_bar;
+ dec->black_bar_updated = 1;
+}
+
+static unsigned int __mfc_handle_frame_field(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ unsigned int interlace_type = 0, is_interlace = 0, is_mbaff = 0;
+ unsigned int field;
+
+ if (CODEC_INTERLACED(ctx))
+ is_interlace = mfc_is_interlace_picture();
+
+ if (CODEC_MBAFF(ctx))
+ is_mbaff = mfc_is_mbaff_picture();
+
+ if (is_interlace) {
+ interlace_type = mfc_get_interlace_type();
+ if (interlace_type)
+ field = V4L2_FIELD_INTERLACED_TB;
+ else
+ field = V4L2_FIELD_INTERLACED_BT;
+ } else if (is_mbaff) {
+ field = V4L2_FIELD_INTERLACED_TB;
+ } else {
+ field = V4L2_FIELD_NONE;
+ }
+
+ mfc_debug(2, "[INTERLACE] is_interlace: %d (type : %d), is_mbaff: %d, field: 0x%#x\n",
+ is_interlace, interlace_type, is_mbaff, field);
+
+ return field;
+}
+
+static void __mfc_handle_frame_all_extracted(struct mfc_ctx *ctx)
+{
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_buf *dst_mb;
+ int index, i, is_first = 1;
+
+ mfc_debug(2, "Decided to finish\n");
+ ctx->sequence++;
+
+ while (1) {
+ dst_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (!dst_mb)
+ break;
+
+ mfc_debug(2, "Cleaning up buffer: %d\n",
+ dst_mb->vb.vb2_buf.index);
+
+ index = dst_mb->vb.vb2_buf.index;
+
+ for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
+ vb2_set_plane_payload(&dst_mb->vb.vb2_buf, i, 0);
+
+ dst_mb->vb.sequence = (ctx->sequence++);
+ dst_mb->vb.field = __mfc_handle_frame_field(ctx);
+ dst_mb->vb.reserved2 = 0;
+
+ clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
+
+ if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
+ mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+ if (is_first) {
+ call_cop(ctx, get_buf_update_val, ctx,
+ &ctx->dst_ctrls[index],
+ V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ dec->stored_tag);
+ is_first = 0;
+ } else {
+ call_cop(ctx, get_buf_update_val, ctx,
+ &ctx->dst_ctrls[index],
+ V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ DEFAULT_TAG);
+ call_cop(ctx, get_buf_update_val, ctx,
+ &ctx->dst_ctrls[index],
+ V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
+ 0);
+ }
+
+ vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+ /* decoder dst buffer CFW UNPROT */
+ if (ctx->is_drm)
+ mfc_raw_unprotect(ctx, dst_mb, index);
+
+ mfc_debug(2, "Cleaned up buffer: %d\n", index);
+ }
+
+ mfc_handle_force_change_status(ctx);
+ mfc_debug(2, "After cleanup\n");
+}
+
+static void __mfc_handle_frame_copy_timestamp(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_buf *ref_mb, *src_mb;
+ dma_addr_t dec_y_addr;
+
+ dec_y_addr = (dma_addr_t)mfc_get_dec_y_addr();
+
+ /* Get the source buffer */
+ src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (!src_mb) {
+ mfc_err_dev("[TS] no src buffers\n");
+ return;
+ }
+
+ ref_mb = mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr);
+ if (ref_mb)
+ ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp;
+}
+
+static void __mfc_handle_frame_output_move(struct mfc_ctx *ctx,
+ dma_addr_t dspl_y_addr, unsigned int released_flag)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_buf *ref_mb;
+ int index;
+
+ ref_mb = mfc_find_move_buf(&ctx->buf_queue_lock,
+ &ctx->dst_buf_queue, &ctx->ref_buf_queue, dspl_y_addr, released_flag);
+ if (ref_mb) {
+ index = ref_mb->vb.vb2_buf.index;
+
+ /* Check if this is the buffer we're looking for */
+ mfc_debug(2, "[DPB] Found buf[%d] 0x%08llx, looking for disp addr 0x%08llx\n",
+ index, ref_mb->addr[0][0], dspl_y_addr);
+
+ if (released_flag & (1 << index)) {
+ dec->available_dpb &= ~(1 << index);
+ released_flag &= ~(1 << index);
+ mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(release)\n",
+ mfc_get_warn(mfc_get_int_err()));
+ } else {
+ dec->err_reuse_flag |= 1 << index;
+ mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(not released)\n",
+ mfc_get_warn(mfc_get_int_err()));
+ }
+ dec->dynamic_used |= released_flag;
+ }
+}
+
+static void __mfc_handle_frame_output_del(struct mfc_ctx *ctx,
+ unsigned int err, unsigned int released_flag)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_raw_info *raw = &ctx->raw_buf;
+ struct mfc_buf *ref_mb;
+ dma_addr_t dspl_y_addr;
+ unsigned int frame_type;
+ unsigned int dst_frame_status;
+ unsigned int is_video_signal_type = 0, is_colour_description = 0;
+ unsigned int is_content_light = 0, is_display_colour = 0;
+ unsigned int i, index;
+
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+ is_video_signal_type = mfc_get_video_signal_type();
+ is_colour_description = mfc_get_colour_description();
+ }
+
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
+ is_content_light = mfc_get_sei_avail_content_light();
+ is_display_colour = mfc_get_sei_avail_mastering_display();
+ }
+
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar)
+ __mfc_handle_black_bar_info(dev, ctx);
+ else
+ dec->black_bar_updated = 0;
+
+ if (dec->immediate_display == 1) {
+ dspl_y_addr = (dma_addr_t)mfc_get_dec_y_addr();
+ frame_type = mfc_get_dec_frame_type();
+ } else {
+ dspl_y_addr = (dma_addr_t)mfc_get_disp_y_addr();
+ frame_type = mfc_get_disp_frame_type();
+ }
+
+ ref_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
+ &ctx->ref_buf_queue, dspl_y_addr);
+ if (ref_mb) {
+ index = ref_mb->vb.vb2_buf.index;
+ /* Check if this is the buffer we're looking for */
+ mfc_debug(2, "[BUFINFO][DPB] ctx[%d] get dst index: %d, addr[0]: 0x%08llx\n",
+ ctx->num, index, ref_mb->addr[0][0]);
+
+ ref_mb->vb.sequence = ctx->sequence;
+ ref_mb->vb.field = __mfc_handle_frame_field(ctx);
+
+ /* Set reserved2 bits in order to inform SEI information */
+ ref_mb->vb.reserved2 = 0;
+
+ if (is_content_light) {
+ ref_mb->vb.reserved2 |= (1 << 0);
+ mfc_debug(2, "[HDR] content light level parsed\n");
+ }
+
+ if (is_display_colour) {
+ ref_mb->vb.reserved2 |= (1 << 1);
+ mfc_debug(2, "[HDR] mastering display colour parsed\n");
+ }
+
+ if (is_video_signal_type) {
+ ref_mb->vb.reserved2 |= (1 << 4);
+ mfc_debug(2, "[HDR] video signal type parsed\n");
+ if (is_colour_description) {
+ ref_mb->vb.reserved2 |= (1 << 2);
+ mfc_debug(2, "[HDR] matrix coefficients parsed\n");
+ ref_mb->vb.reserved2 |= (1 << 3);
+ mfc_debug(2, "[HDR] colour description parsed\n");
+ }
+ }
+
+ if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+ if (dec->color_space != MFC_REG_D_COLOR_UNKNOWN) {
+ ref_mb->vb.reserved2 |= (1 << 3);
+ mfc_debug(2, "[HDR] color space parsed\n");
+ }
+ ref_mb->vb.reserved2 |= (1 << 4);
+ mfc_debug(2, "[HDR] color range parsed\n");
+ }
+
+ if (dec->black_bar_updated) {
+ ref_mb->vb.reserved2 |= (1 << 5);
+ mfc_debug(3, "[BLACKBAR] black bar detected\n");
+ }
+
+ if (ctx->src_fmt->mem_planes == 1) {
+ vb2_set_plane_payload(&ref_mb->vb.vb2_buf, 0,
+ raw->total_plane_size);
+ mfc_debug(5, "single plane payload: %d\n",
+ raw->total_plane_size);
+ } else {
+ for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+ vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i,
+ raw->plane_size[i]);
+ }
+ }
+
+ clear_bit(index, &dec->available_dpb);
+
+ ref_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+ V4L2_BUF_FLAG_PFRAME |
+ V4L2_BUF_FLAG_BFRAME |
+ V4L2_BUF_FLAG_ERROR);
+
+ switch (frame_type) {
+ case MFC_REG_DISPLAY_FRAME_I:
+ ref_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ break;
+ case MFC_REG_DISPLAY_FRAME_P:
+ ref_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+ break;
+ case MFC_REG_DISPLAY_FRAME_B:
+ ref_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+ break;
+ default:
+ break;
+ }
+
+ if (mfc_get_warn(err)) {
+ mfc_err_ctx("Warning for displayed frame: %d\n",
+ mfc_get_warn(err));
+ ref_mb->vb.flags |= V4L2_BUF_FLAG_ERROR;
+ }
+
+ if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
+ mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+ mfc_handle_released_info(ctx, released_flag, index);
+
+ if (dec->immediate_display == 1) {
+ dst_frame_status = mfc_get_dec_status();
+
+ call_cop(ctx, get_buf_update_val, ctx,
+ &ctx->dst_ctrls[index],
+ V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
+ dst_frame_status);
+
+ call_cop(ctx, get_buf_update_val, ctx,
+ &ctx->dst_ctrls[index],
+ V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ dec->stored_tag);
+
+ dec->immediate_display = 0;
+ }
+
+ /* Update frame tag for packed PB */
+ if (CODEC_MULTIFRAME(ctx) && (dec->y_addr_for_pb == dspl_y_addr)) {
+ call_cop(ctx, get_buf_update_val, ctx,
+ &ctx->dst_ctrls[index],
+ V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+ dec->stored_tag);
+ dec->y_addr_for_pb = 0;
+ }
+
+ mfc_qos_update_last_framerate(ctx, ref_mb->vb.vb2_buf.timestamp);
+ vb2_buffer_done(&ref_mb->vb.vb2_buf, mfc_get_warn(err) ?
+ VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+ }
+}
+
+static void __mfc_handle_frame_new(struct mfc_ctx *ctx, unsigned int err)
+{
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_dev *dev = ctx->dev;
+ dma_addr_t dspl_y_addr;
+ unsigned int frame_type;
+ int mvc_view_id;
+ unsigned int prev_flag, released_flag = 0;
+
+ frame_type = mfc_get_disp_frame_type();
+ mvc_view_id = mfc_get_mvc_disp_view_id();
+
+ if (IS_H264_MVC_DEC(ctx)) {
+ if (mvc_view_id == 0)
+ ctx->sequence++;
+ } else {
+ ctx->sequence++;
+ }
+
+ dspl_y_addr = mfc_get_disp_y_addr();
+
+ if (dec->immediate_display == 1) {
+ dspl_y_addr = (dma_addr_t)mfc_get_dec_y_addr();
+ frame_type = mfc_get_dec_frame_type();
+ }
+
+ mfc_debug(2, "[FRAME] frame type: %d\n", frame_type);
+
+ /* If frame is same as previous then skip and do not dequeue */
+ if (frame_type == MFC_REG_DISPLAY_FRAME_NOT_CODED)
+ if (!CODEC_NOT_CODED(ctx))
+ return;
+
+ prev_flag = dec->dynamic_used;
+ dec->dynamic_used = mfc_get_dec_used_flag();
+ released_flag = prev_flag & (~dec->dynamic_used);
+
+ mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x, Released buffer = %08x\n",
+ prev_flag, dec->dynamic_used, released_flag);
+
+ /* decoder dst buffer CFW UNPROT */
+ mfc_unprotect_released_dpb(ctx, released_flag);
+
+ if ((IS_VC1_RCV_DEC(ctx) &&
+ mfc_get_warn(err) == MFC_REG_ERR_SYNC_POINT_NOT_RECEIVED) ||
+ (mfc_get_warn(err) == MFC_REG_ERR_BROKEN_LINK))
+ __mfc_handle_frame_output_move(ctx, dspl_y_addr, released_flag);
+ else
+ __mfc_handle_frame_output_del(ctx, err, released_flag);
+}
+
+static void __mfc_handle_frame_error(struct mfc_ctx *ctx,
+ unsigned int reason, unsigned int err)
+{
+ struct mfc_dec *dec;
+ struct mfc_buf *src_mb;
+ unsigned int index;
+
+ if (ctx->type == MFCINST_ENCODER) {
+ mfc_err_ctx("Encoder Interrupt Error: %d\n", err);
+ return;
+ }
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return;
+ }
+
+ mfc_err_ctx("Interrupt Error: %d\n", err);
+
+ /* Get the source buffer */
+ src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+
+ if (!src_mb) {
+ mfc_err_dev("no src buffers\n");
+ } else {
+ index = src_mb->vb.vb2_buf.index;
+ if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+ mfc_debug(2, "MFC needs next buffer\n");
+ dec->consumed = 0;
+
+ if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+ /* decoder src buffer CFW UNPROT */
+ if (ctx->is_drm)
+ mfc_stream_unprotect(ctx, src_mb, index);
+
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
+
+ mfc_debug(2, "Assesing whether this context should be run again\n");
+}
+
+static void __mfc_handle_ref_frame(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_buf *dst_mb;
+ dma_addr_t dec_addr;
+
+ dec_addr = (dma_addr_t)mfc_get_dec_y_addr();
+
+ /* Try to search decoded address in whole dst queue */
+ dst_mb = mfc_find_move_buf_used(&ctx->buf_queue_lock,
+ &ctx->ref_buf_queue, &ctx->dst_buf_queue, dec_addr);
+ if (dst_mb) {
+ mfc_debug(2, "[DPB] Found in dst queue = 0x%08llx, buf = 0x%08llx\n",
+ dec_addr, dst_mb->addr[0][0]);
+
+ if (!(dec->dynamic_set & mfc_get_dec_used_flag()))
+ dec->dynamic_used |= dec->dynamic_set;
+ } else {
+ mfc_debug(2, "[DPB] Can't find buffer for addr = 0x%08llx\n", dec_addr);
+ }
+}
+
+static void __mfc_handle_reuse_buffer(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ unsigned int prev_flag, released_flag = 0;
+ int i;
+
+ prev_flag = dec->dynamic_used;
+ dec->dynamic_used = mfc_get_dec_used_flag();
+ released_flag = prev_flag & (~dec->dynamic_used);
+
+ if (!released_flag)
+ return;
+
+ /* Reuse not referenced buf anymore */
+ for (i = 0; i < MFC_MAX_DPBS; i++)
+ if (released_flag & (1 << i))
+ if (mfc_move_reuse_buffer(ctx, i))
+ released_flag &= ~(1 << i);
+
+ /* Not reused buffer should be released when there is a display frame */
+ dec->dec_only_release_flag |= released_flag;
+ for (i = 0; i < MFC_MAX_DPBS; i++)
+ if (released_flag & (1 << i))
+ clear_bit(i, &dec->available_dpb);
+}
+
+static void __mfc_handle_frame_input(struct mfc_ctx *ctx, unsigned int err)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_buf *src_mb;
+ unsigned int index;
+ int deleted = 0;
+ unsigned long consumed;
+
+ consumed = dec->consumed + mfc_get_consumed_stream();
+
+ if (mfc_get_err(err) == MFC_REG_ERR_NON_PAIRED_FIELD) {
+ /*
+ * For non-paired field, the same buffer need to be
+ * resubmitted and the consumed stream will be 0
+ */
+ mfc_debug(2, "Not paired field. Running again the same buffer\n");
+ return;
+ }
+
+ /* Get the source buffer */
+ src_mb = mfc_get_del_if_consumed(ctx, &ctx->src_buf_queue,
+ mfc_get_consumed_stream(), STUFF_BYTE, err, &deleted);
+ if (!src_mb) {
+ mfc_err_dev("no src buffers\n");
+ return;
+ }
+
+ index = src_mb->vb.vb2_buf.index;
+ mfc_debug(2, "[BUFINFO] ctx[%d] get src index: %d, addr: 0x%08llx\n",
+ ctx->num, index, src_mb->addr[0][0]);
+
+ if (!deleted) {
+ /* Run MFC again on the same buffer */
+ mfc_debug(2, "[MULTIFRAME] Running again the same buffer\n");
+
+ if (CODEC_MULTIFRAME(ctx))
+ dec->y_addr_for_pb = (dma_addr_t)mfc_get_dec_y_addr();
+
+ dec->consumed = consumed;
+ dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused
+ - dec->consumed;
+ dec->has_multiframe = 1;
+
+ MFC_TRACE_CTX("** consumed:%ld, remained:%ld, addr:0x%08llx\n",
+ dec->consumed, dec->remained_size, dec->y_addr_for_pb);
+ /* Do not move src buffer to done_list */
+ return;
+ }
+
+ if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+ dec->consumed = 0;
+ dec->remained_size = 0;
+
+ if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+ /* decoder src buffer CFW UNPROT */
+ if (ctx->is_drm)
+ mfc_stream_unprotect(ctx, src_mb, index);
+
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+/* Handle frame decoding interrupt */
+static void __mfc_handle_frame(struct mfc_ctx *ctx,
+ unsigned int reason, unsigned int err)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ unsigned int dst_frame_status, sei_avail_frame_pack;
+ unsigned int res_change, need_dpb_change, need_scratch_change;
+
+ dst_frame_status = mfc_get_disp_status();
+ res_change = mfc_get_res_change();
+ need_dpb_change = mfc_get_dpb_change();
+ need_scratch_change = mfc_get_scratch_change();
+ sei_avail_frame_pack = mfc_get_sei_avail_frame_pack();
+
+ if (dec->immediate_display == 1)
+ dst_frame_status = mfc_get_dec_status();
+
+ mfc_debug(2, "[FRAME] frame status: %d\n", dst_frame_status);
+ mfc_debug(2, "[FRAME] display status: %d, type: %d, yaddr: %#x\n",
+ mfc_get_disp_status(), mfc_get_disp_frame_type(),
+ mfc_get_disp_y_addr());
+ mfc_debug(2, "[FRAME] decoded status: %d, type: %d, yaddr: %#x\n",
+ mfc_get_dec_status(), mfc_get_dec_frame_type(),
+ mfc_get_dec_y_addr());
+
+ mfc_debug(4, "[HDR] SEI available status: 0x%08x\n", mfc_get_sei_avail());
+ mfc_debug(4, "[HDR] SEI content light: 0x%08x\n", mfc_get_sei_content_light());
+ mfc_debug(4, "[HDR] SEI luminance: 0x%08x, 0x%08x white point: 0x%08x\n",
+ mfc_get_sei_mastering0(), mfc_get_sei_mastering1(),
+ mfc_get_sei_mastering2());
+ mfc_debug(4, "[HDR] SEI display primaries: 0x%08x, 0x%08x, 0x%08x\n",
+ mfc_get_sei_mastering3(), mfc_get_sei_mastering4(),
+ mfc_get_sei_mastering5());
+ mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x\n",
+ dec->dynamic_used, mfc_get_dec_used_flag());
+
+ if (ctx->state == MFCINST_RES_CHANGE_INIT)
+ mfc_change_state(ctx, MFCINST_RES_CHANGE_FLUSH);
+
+ if (res_change) {
+ mfc_debug(2, "[DRC] Resolution change set to %d\n", res_change);
+ mfc_change_state(ctx, MFCINST_RES_CHANGE_INIT);
+ ctx->wait_state = WAIT_DECODING;
+ mfc_debug(7, "[DRC] Decoding waiting! : %d\n", ctx->wait_state);
+ return;
+ }
+
+ if (need_dpb_change || need_scratch_change)
+ mfc_debug(2, "[DRC] Interframe resolution change is not supported\n");
+
+ if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0) &&
+ mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
+ mfc_err_dev("Queue count is zero for src and dst\n");
+ goto leave_handle_frame;
+ }
+
+ if (IS_H264_DEC(ctx) && sei_avail_frame_pack &&
+ dst_frame_status == MFC_REG_DEC_STATUS_DECODING_ONLY) {
+ mfc_debug(2, "Frame packing SEI exists for a frame\n");
+ mfc_debug(2, "Reallocate DPBs and issue init_buffer\n");
+ ctx->is_dpb_realloc = 1;
+ mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+ ctx->capture_state = QUEUE_FREE;
+ ctx->wait_state = WAIT_DECODING;
+ __mfc_handle_frame_all_extracted(ctx);
+ goto leave_handle_frame;
+ }
+
+ /* All frames remaining in the buffer have been extracted */
+ if (dst_frame_status == MFC_REG_DEC_STATUS_DECODING_EMPTY) {
+ if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
+ struct mfc_timestamp *temp_ts = NULL;
+
+ mfc_debug(2, "[DRC] Last frame received after resolution change\n");
+ __mfc_handle_frame_all_extracted(ctx);
+ mfc_change_state(ctx, MFCINST_RES_CHANGE_END);
+ /* If there is no display frame after resolution change,
+ * Some released frames can't be unprotected.
+ * So, check and request unprotection in the end of DRC.
+ */
+ mfc_cleanup_assigned_dpb(ctx);
+
+ /* empty the timestamp queue */
+ while (!list_empty(&ctx->ts_list)) {
+ temp_ts = list_entry((&ctx->ts_list)->next,
+ struct mfc_timestamp, list);
+ list_del(&temp_ts->list);
+ }
+ ctx->ts_count = 0;
+ ctx->ts_is_full = 0;
+ mfc_qos_reset_last_framerate(ctx);
+ mfc_qos_set_framerate(ctx, DEC_DEFAULT_FPS);
+
+ goto leave_handle_frame;
+ } else {
+ __mfc_handle_frame_all_extracted(ctx);
+ }
+ }
+
+ if (mfc_get_num_of_tile() >= 4)
+ dec->num_of_tile_over_4 = 1;
+
+ switch (dst_frame_status) {
+ case MFC_REG_DEC_STATUS_DECODING_DISPLAY:
+ __mfc_handle_ref_frame(ctx);
+ break;
+ case MFC_REG_DEC_STATUS_DECODING_ONLY:
+ __mfc_handle_ref_frame(ctx);
+ /*
+ * Some cases can have many decoding only frames like VP9
+ * alt-ref frame. So need handling release buffer
+ * because of DPB full.
+ */
+ __mfc_handle_reuse_buffer(ctx);
+ break;
+ default:
+ break;
+ }
+
+ if (mfc_dec_status_decoding(dst_frame_status))
+ __mfc_handle_frame_copy_timestamp(ctx);
+
+ /* A frame has been decoded and is in the buffer */
+ if (mfc_dec_status_display(dst_frame_status))
+ __mfc_handle_frame_new(ctx, err);
+ else
+ mfc_debug(2, "No frame decode\n");
+
+ /* Mark source buffer as complete */
+ if (dst_frame_status != MFC_REG_DEC_STATUS_DISPLAY_ONLY)
+ __mfc_handle_frame_input(ctx, err);
+
+leave_handle_frame:
+ mfc_debug(2, "Assesing whether this context should be run again\n");
+}
+
+static void __mfc_handle_stream_copy_timestamp(struct mfc_ctx *ctx, struct mfc_buf *src_mb)
+{
+ struct mfc_dev *dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_enc_params *p = &enc->params;
+ struct mfc_buf *dst_mb;
+ u32 interval;
+ u64 start_timestamp;
+ u64 new_timestamp;
+
+ if (!ctx) {
+ mfc_err_dev("[BUFCON][TS] no mfc context to run\n");
+ return;
+ }
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("[BUFCON][TS] no device to run\n");
+ return;
+ }
+
+ start_timestamp = src_mb->vb.vb2_buf.timestamp;
+ interval = NSEC_PER_SEC / p->rc_framerate;
+ if (debug_ts == 1)
+ mfc_info_ctx("[BUFCON][TS] %dfps, start timestamp: %lld, base interval: %d\n",
+ p->rc_framerate, start_timestamp, interval);
+
+ new_timestamp = start_timestamp + (interval * src_mb->done_index);
+ if (debug_ts == 1)
+ mfc_info_ctx("[BUFCON][TS] new timestamp: %lld, interval: %d\n",
+ new_timestamp, interval * src_mb->done_index);
+
+ /* Get the destination buffer */
+ dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (dst_mb)
+ dst_mb->vb.vb2_buf.timestamp = new_timestamp;
+}
+
+static void __mfc_handle_stream_input(struct mfc_ctx *ctx)
+{
+ struct mfc_raw_info *raw;
+ struct mfc_buf *ref_mb, *src_mb;
+ dma_addr_t enc_addr[3] = { 0, 0, 0 };
+ int i, found_in_src_queue = 0;
+ unsigned int index;
+
+ raw = &ctx->raw_buf;
+
+ mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
+ if (enc_addr[0] == 0) {
+ mfc_debug(3, "no encoded src\n");
+ goto move_buf;
+ }
+ for (i = 0; i < raw->num_planes; i++)
+ mfc_debug(2, "[BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
+ ctx->num, i, enc_addr[i]);
+
+ if (IS_BUFFER_BATCH_MODE(ctx)) {
+ src_mb = mfc_find_first_buf(&ctx->buf_queue_lock,
+ &ctx->src_buf_queue, enc_addr[0]);
+ if (src_mb) {
+ found_in_src_queue = 1;
+
+ __mfc_handle_stream_copy_timestamp(ctx, src_mb);
+ src_mb->done_index++;
+ mfc_debug(4, "[BUFCON] batch buf done_index: %d\n", src_mb->done_index);
+
+ index = src_mb->vb.vb2_buf.index;
+
+ if (call_cop(ctx, recover_buf_ctrls_val, ctx,
+ &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+ /* single buffer || last image in a buffer container */
+ if (!src_mb->num_valid_bufs || src_mb->done_index == src_mb->num_valid_bufs) {
+ src_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
+ &ctx->src_buf_queue, enc_addr[0]);
+ for (i = 0; i < raw->num_planes; i++)
+ mfc_bufcon_put_daddr(ctx, src_mb, i);
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+
+ /* encoder src buffer CFW UNPROT */
+ if (ctx->is_drm)
+ mfc_raw_unprotect(ctx, src_mb, index);
+ }
+ } else {
+ /* normal single buffer */
+ src_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
+ &ctx->src_buf_queue, enc_addr[0]);
+ if (src_mb) {
+ found_in_src_queue = 1;
+ index = src_mb->vb.vb2_buf.index;
+ if (call_cop(ctx, recover_buf_ctrls_val, ctx,
+ &ctx->src_ctrls[index]) < 0)
+ mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+ mfc_debug(3, "find src buf in src_queue\n");
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+ /* encoder src buffer CFW UNPROT */
+ if (ctx->is_drm)
+ mfc_raw_unprotect(ctx, src_mb, index);
+ } else {
+ mfc_debug(3, "no src buf in src_queue\n");
+ ref_mb = mfc_find_del_buf(&ctx->buf_queue_lock,
+ &ctx->ref_buf_queue, enc_addr[0]);
+ if (ref_mb) {
+ mfc_debug(3, "find src buf in ref_queue\n");
+ vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+ /* encoder src buffer CFW UNPROT */
+ if (ctx->is_drm) {
+ index = ref_mb->vb.vb2_buf.index;
+ mfc_raw_unprotect(ctx, ref_mb, index);
+ }
+ } else {
+ mfc_err_ctx("couldn't find src buffer\n");
+ }
+ }
+ }
+
+move_buf:
+ /* move enqueued src buffer: src queue -> ref queue */
+ if (!found_in_src_queue && ctx->state != MFCINST_FINISHING) {
+ mfc_move_first_buf_used(&ctx->buf_queue_lock,
+ &ctx->ref_buf_queue, &ctx->src_buf_queue, MFC_QUEUE_ADD_BOTTOM);
+
+ mfc_debug(2, "enc src_buf_queue(%d) -> ref_buf_queue(%d)\n",
+ mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+ mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
+ }
+}
+
+static void __mfc_handle_stream_output(struct mfc_ctx *ctx, int slice_type,
+ unsigned int strm_size)
+{
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_buf *dst_mb;
+ unsigned int index;
+
+ if (strm_size == 0) {
+ mfc_debug(3, "no encoded dst (reuse)\n");
+ return;
+ } else if (strm_size < 0) {
+ mfc_err_ctx("invalid stream size: %d\n", strm_size);
+ return;
+ }
+
+ /* at least one more dest. buffers exist always */
+ dst_mb = mfc_get_del_buf(&ctx->buf_queue_lock,
+ &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (!dst_mb) {
+ mfc_err_ctx("no dst buffers\n");
+ return;
+ }
+
+ mfc_debug(2, "[BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
+ ctx->num, dst_mb->addr[0][0]);
+
+ dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+ V4L2_BUF_FLAG_PFRAME |
+ V4L2_BUF_FLAG_BFRAME);
+ switch (slice_type) {
+ case MFC_REG_E_SLICE_TYPE_I:
+ dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ break;
+ case MFC_REG_E_SLICE_TYPE_P:
+ dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+ break;
+ case MFC_REG_E_SLICE_TYPE_B:
+ dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+ break;
+ default:
+ dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ break;
+ }
+ mfc_debug(2, "[STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
+
+ if (IS_BPG_ENC(ctx)) {
+ strm_size += enc->header_size;
+ mfc_debug(2, "bpg total stream size: %d\n", strm_size);
+ }
+ vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
+
+ index = dst_mb->vb.vb2_buf.index;
+ if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
+ mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+ vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+ /* encoder dst buffer CFW UNPROT */
+ if (ctx->is_drm)
+ mfc_stream_unprotect(ctx, dst_mb, index);
+}
+
+/* Handle frame encoding interrupt */
+static int __mfc_handle_stream(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ int slice_type;
+ unsigned int strm_size;
+ unsigned int pic_count;
+
+ slice_type = mfc_get_enc_slice_type();
+ strm_size = mfc_get_enc_strm_size();
+ pic_count = mfc_get_enc_pic_count();
+
+ mfc_debug(2, "[STREAM] encoded slice type: %d, size: %d, display order: %d\n",
+ slice_type, strm_size, pic_count);
+
+ /* buffer full handling */
+ if (enc->buf_full) {
+ mfc_change_state(ctx, MFCINST_ABORT_INST);
+ return 0;
+ }
+ if (ctx->state == MFCINST_RUNNING_BUF_FULL)
+ mfc_change_state(ctx, MFCINST_RUNNING);
+
+ /* set encoded frame type */
+ enc->frame_type = slice_type;
+ ctx->sequence++;
+
+ if (enc->in_slice) {
+ if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
+ mfc_clear_bit(ctx->num, &dev->work_bits);
+ }
+ return 0;
+ }
+
+ /* handle source buffer */
+ __mfc_handle_stream_input(ctx);
+
+ /* handle destination buffer */
+ __mfc_handle_stream_output(ctx, slice_type, strm_size);
+
+ return 0;
+}
+
+/* Error handling for interrupt */
+static inline void __mfc_handle_error(struct mfc_ctx *ctx,
+ unsigned int reason, unsigned int err)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_buf *src_mb;
+ int index;
+
+ mfc_err_ctx("Interrupt Error: display: %d, decoded: %d\n",
+ mfc_get_warn(err), mfc_get_err(err));
+ err = mfc_get_err(err);
+
+ /* Error recovery is dependent on the state of context */
+ switch (ctx->state) {
+ case MFCINST_RES_CHANGE_END:
+ case MFCINST_GOT_INST:
+ /* This error had to happen while parsing the header */
+ if (!ctx->is_drm) {
+ unsigned char *stream_vir = NULL;
+ unsigned int strm_size = 0;
+
+ src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (src_mb) {
+ stream_vir = src_mb->vir_addr;
+ strm_size = src_mb->vb.vb2_buf.planes[0].bytesused;
+ if (strm_size > 32)
+ strm_size = 32;
+
+ if (stream_vir && strm_size)
+ print_hex_dump(KERN_ERR, "No header: ",
+ DUMP_PREFIX_ADDRESS, strm_size, 0,
+ stream_vir, strm_size, false);
+
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+ } else {
+ src_mb = mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (src_mb) {
+ index = src_mb->vb.vb2_buf.index;
+ /* decoder src buffer CFW UNPROT */
+ mfc_stream_unprotect(ctx, src_mb, index);
+ vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+ }
+ break;
+ case MFCINST_INIT:
+ /* This error had to happen while acquireing instance */
+ case MFCINST_RETURN_INST:
+ /* This error had to happen while releasing instance */
+ case MFCINST_DPB_FLUSHING:
+ /* This error had to happen while flushing DPB */
+ case MFCINST_SPECIAL_PARSING:
+ case MFCINST_SPECIAL_PARSING_NAL:
+ /* This error had to happen while special parsing */
+ break;
+ case MFCINST_HEAD_PARSED:
+ /* This error had to happen while setting dst buffers */
+ case MFCINST_RES_CHANGE_INIT:
+ case MFCINST_RES_CHANGE_FLUSH:
+ /* This error has to happen while resolution change */
+ case MFCINST_ABORT_INST:
+ /* This error has to happen while buffer full handling */
+ case MFCINST_FINISHING:
+ /* It is higly probable that an error occured
+ * while decoding a frame */
+ mfc_change_state(ctx, MFCINST_ERROR);
+ /* Mark all dst buffers as having an error */
+ mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
+ /* Mark all src buffers as having an error */
+ mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_queue);
+ break;
+ default:
+ mfc_err_ctx("Encountered an error interrupt which had not been handled\n");
+ mfc_err_ctx("ctx->state = %d, ctx->inst_no = %d\n",
+ ctx->state, ctx->inst_no);
+ break;
+ }
+
+ mfc_wake_up_dev(dev, reason, err);
+
+ return;
+}
+
+/* Handle header decoder interrupt */
+static int __mfc_handle_seq_dec(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ int i, is_interlace, is_mbaff;
+
+ if (ctx->src_fmt->fourcc != V4L2_PIX_FMT_FIMV1) {
+ ctx->img_width = mfc_get_img_width();
+ ctx->img_height = mfc_get_img_height();
+ ctx->crop_width = ctx->img_width;
+ ctx->crop_height = ctx->img_height;
+ mfc_info_ctx("[STREAM] resolution w: %d, h: %d\n", ctx->img_width, ctx->img_height);
+ }
+
+ ctx->dpb_count = mfc_get_dpb_count();
+ ctx->scratch_buf_size = mfc_get_scratch_size();
+ for (i = 0; i < ctx->dst_fmt->num_planes; i++)
+ ctx->min_dpb_size[i] = mfc_get_min_dpb_size(i);
+
+ mfc_dec_store_crop_info(ctx);
+ dec->mv_count = mfc_get_mv_count();
+ if (CODEC_10BIT(ctx) && dev->pdata->support_10bit) {
+ if (mfc_get_luma_bit_depth_minus8() ||
+ mfc_get_chroma_bit_depth_minus8() ||
+ mfc_get_profile() == MFC_REG_D_PROFILE_HEVC_MAIN_10) {
+ ctx->is_10bit = 1;
+ mfc_info_ctx("[STREAM][10BIT] 10bit contents, profile: %d, depth: %d/%d\n",
+ mfc_get_profile(),
+ mfc_get_luma_bit_depth_minus8() + 8,
+ mfc_get_chroma_bit_depth_minus8() + 8);
+ }
+ }
+ if (CODEC_422FORMAT(ctx) && dev->pdata->support_422) {
+ if (mfc_get_chroma_format() == MFC_REG_D_CHROMA_422) {
+ ctx->is_422 = 1;
+ mfc_info_ctx("[STREAM] 422 chroma format\n");
+ }
+ }
+
+ if (ctx->img_width == 0 || ctx->img_height == 0)
+ mfc_change_state(ctx, MFCINST_ERROR);
+ else
+ mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+
+ if (ctx->state == MFCINST_HEAD_PARSED) {
+ is_interlace = mfc_is_interlace_picture();
+ is_mbaff = mfc_is_mbaff_picture();
+ if (is_interlace || is_mbaff)
+ dec->is_interlaced = 1;
+ mfc_debug(2, "[INTERLACE] interlace: %d, mbaff: %d\n", is_interlace, is_mbaff);
+ }
+
+ if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx)) {
+ struct mfc_buf *src_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (src_mb) {
+ dec->consumed += mfc_get_consumed_stream();
+ mfc_debug(2, "[STREAM] header total size : %d, consumed : %lu\n",
+ src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed);
+ if ((dec->consumed > 0) &&
+ (src_mb->vb.vb2_buf.planes[0].bytesused > dec->consumed)) {
+ dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused -
+ dec->consumed;
+ mfc_debug(2, "[STREAM] there is remained bytes(%lu) after header parsing\n",
+ dec->remained_size);
+ } else {
+ dec->consumed = 0;
+ dec->remained_size = 0;
+ }
+ }
+ }
+
+ if (IS_VP9_DEC(ctx)) {
+ dec->color_range = mfc_get_color_range();
+ dec->color_space = mfc_get_color_space();
+ mfc_debug(2, "color range: %d, color space: %d, It's valid for VP9\n",
+ dec->color_range, dec->color_space);
+ }
+
+ return 0;
+}
+
+/* Handle header encoder interrupt */
+static int __mfc_handle_seq_enc(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ struct mfc_enc_params *p = &enc->params;
+ struct mfc_buf *dst_mb;
+ int ret;
+
+ enc->header_size = mfc_get_enc_strm_size();
+ mfc_debug(2, "[STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
+ mfc_get_enc_slice_type(), enc->header_size,
+ mfc_get_enc_pic_count());
+
+ if (IS_BPG_ENC(ctx)) {
+ dst_mb = mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (!dst_mb) {
+ mfc_err_dev("no dst buffers\n");
+ return -EAGAIN;
+ }
+
+ dst_mb->vb.vb2_buf.planes[0].data_offset += (enc->header_size +
+ p->codec.bpg.thumb_size + p->codec.bpg.exif_size);
+ mfc_debug(2, "offset for NAL_START: %d (header: %d + thumb: %d + exif: %d)\n",
+ dst_mb->vb.vb2_buf.planes[0].data_offset,
+ enc->header_size,
+ p->codec.bpg.thumb_size,
+ p->codec.bpg.exif_size);
+ } else {
+ if ((p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) ||
+ (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY)) {
+ dst_mb = mfc_get_del_buf(&ctx->buf_queue_lock,
+ &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+ if (!dst_mb) {
+ mfc_err_dev("no dst buffers\n");
+ return -EAGAIN;
+ }
+
+ vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, mfc_get_enc_strm_size());
+ vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+ /* encoder dst buffer CFW UNPROT */
+ if (ctx->is_drm) {
+ int index = dst_mb->vb.vb2_buf.index;
+
+ mfc_stream_unprotect(ctx, dst_mb, index);
+ }
+ }
+ }
+
+ ctx->dpb_count = mfc_get_enc_dpb_count();
+ ctx->scratch_buf_size = mfc_get_enc_scratch_size();
+
+ /* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */
+ mfc_clear_roi_enable(dev);
+
+ if (!ctx->codec_buffer_allocated) {
+ mfc_debug(2, "[DRC] previous codec buffer is exist\n");
+
+ if (dev->has_mmcache && dev->mmcache.is_on_status)
+ mfc_invalidate_mmcache(dev);
+
+ mfc_release_codec_buffers(ctx);
+ }
+ ret = mfc_alloc_codec_buffers(ctx);
+ if (ret) {
+ mfc_err_ctx("Failed to allocate encoding buffers\n");
+ return ret;
+ }
+
+ mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+
+ return 0;
+}
+
+static inline int is_err_condition(unsigned int err)
+{
+ if (err == MFC_REG_ERR_NO_AVAILABLE_DPB ||
+ err == MFC_REG_ERR_INSUFFICIENT_DPB_SIZE ||
+ err == MFC_REG_ERR_INSUFFICIENT_NUM_DPB ||
+ err == MFC_REG_ERR_INSUFFICIENT_MV_BUF_SIZE ||
+ err == MFC_REG_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE)
+ return 1;
+
+ return 0;
+}
+
+irqreturn_t mfc_top_half_irq(int irq, void *priv)
+{
+ struct mfc_dev *dev = priv;
+ struct mfc_ctx *ctx;
+ unsigned int err;
+ unsigned int reason;
+
+ ctx = dev->ctx[dev->curr_ctx];
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return IRQ_WAKE_THREAD;
+ }
+
+ reason = mfc_get_int_reason();
+ err = mfc_get_int_err();
+ mfc_debug(2, "[c:%d] Int reason: %d (err: %d)\n",
+ dev->curr_ctx, reason, err);
+ MFC_TRACE_CTX("<< INT(top): %d\n", reason);
+
+ mfc_perf_measure_off(dev);
+
+ return IRQ_WAKE_THREAD;
+}
+
+/*
+ * Return value description
+ * 0: NAL-Q is handled successfully
+ * 1: NAL_START command
+ * -1: Error
+*/
+static inline int __mfc_nal_q_irq(struct mfc_dev *dev,
+ unsigned int reason, unsigned int err)
+{
+ int ret = -1;
+ unsigned int errcode;
+
+ nal_queue_handle *nal_q_handle = dev->nal_q_handle;
+ EncoderOutputStr *pOutStr;
+
+ switch (reason) {
+ case MFC_REG_R2H_CMD_QUEUE_DONE_RET:
+ pOutStr = mfc_nal_q_dequeue_out_buf(dev,
+ nal_q_handle->nal_q_out_handle, &errcode);
+ if (pOutStr) {
+ if (mfc_nal_q_handle_out_buf(dev, pOutStr))
+ mfc_err_dev("[NALQ] Failed to handle out buf\n");
+ } else {
+ mfc_err_dev("[NALQ] pOutStr is NULL\n");
+ }
+
+ if (nal_q_handle->nal_q_exception)
+ mfc_set_bit(nal_q_handle->nal_q_out_handle->nal_q_ctx,
+ &dev->work_bits);
+ mfc_clear_int_sfr();
+
+ if (!nal_q_handle->nal_q_exception)
+ mfc_nal_q_clock_off(dev, nal_q_handle);
+
+ ret = 0;
+ break;
+ case MFC_REG_R2H_CMD_COMPLETE_QUEUE_RET:
+ mfc_watchdog_stop_tick(dev);
+ nal_q_handle->nal_q_state = NAL_Q_STATE_CREATED;
+ MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
+ mfc_debug(2, "[NALQ] return to created state\n");
+ mfc_nal_q_cleanup_queue(dev);
+ mfc_nal_q_cleanup_clock(dev);
+ mfc_clear_int_sfr();
+ mfc_pm_clock_off(dev);
+ mfc_wake_up_dev(dev, reason, err);
+
+ ret = 0;
+ break;
+ default:
+ if (nal_q_handle->nal_q_state == NAL_Q_STATE_STARTED ||
+ nal_q_handle->nal_q_state == NAL_Q_STATE_STOPPED) {
+ mfc_err_dev("[NALQ] Should not be here! state: %d, int reason : %d\n",
+ nal_q_handle->nal_q_state, reason);
+ mfc_clear_int_sfr();
+
+ ret = -1;
+ } else {
+ /* NAL START */
+ ret = 1;
+ }
+
+ break;
+ }
+
+ if (ret == 0)
+ queue_work(dev->butler_wq, &dev->butler_work);
+
+ return ret;
+}
+
+static inline int __mfc_handle_done_frame(struct mfc_ctx *ctx,
+ unsigned int reason, unsigned int err)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = NULL;
+
+ if (ctx->type == MFCINST_DECODER) {
+ if (ctx->state == MFCINST_SPECIAL_PARSING_NAL) {
+ mfc_clear_int_sfr();
+ mfc_pm_clock_off(dev);
+ mfc_clear_bit(ctx->num, &dev->work_bits);
+ mfc_change_state(ctx, MFCINST_RUNNING);
+ mfc_wake_up_ctx(ctx, reason, err);
+ return 0;
+ }
+ __mfc_handle_frame(ctx, reason, err);
+ } else if (ctx->type == MFCINST_ENCODER) {
+ if (ctx->otf_handle) {
+ mfc_otf_handle_stream(ctx);
+ return 1;
+ }
+ enc = ctx->enc_priv;
+ if (reason == MFC_REG_R2H_CMD_SLICE_DONE_RET) {
+ dev->preempt_ctx = ctx->num;
+ enc->buf_full = 0;
+ enc->in_slice = 1;
+ } else if (reason == MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET) {
+ mfc_err_ctx("stream buffer size(%d) isn't enough\n",
+ mfc_get_enc_strm_size());
+ dev->preempt_ctx = ctx->num;
+ enc->buf_full = 1;
+ enc->in_slice = 0;
+ } else {
+ enc->buf_full = 0;
+ enc->in_slice = 0;
+ }
+ __mfc_handle_stream(ctx);
+ }
+
+ return 1;
+}
+
+static inline void __mfc_handle_nal_abort(struct mfc_ctx *ctx)
+{
+ struct mfc_enc *enc = ctx->enc_priv;
+
+ if (ctx->type == MFCINST_ENCODER) {
+ mfc_change_state(ctx, MFCINST_RUNNING_BUF_FULL);
+ enc->buf_full = 0;
+ if (IS_VP8_ENC(ctx))
+ mfc_err_ctx("stream buffer size isn't enough\n");
+ __mfc_handle_stream(ctx);
+ } else {
+ mfc_change_state(ctx, MFCINST_ABORT);
+ }
+}
+
+static int __mfc_irq_dev(struct mfc_dev *dev, unsigned int reason, unsigned int err)
+{
+ /* Stop the timeout watchdog */
+ if (reason != MFC_REG_R2H_CMD_FW_STATUS_RET)
+ mfc_watchdog_stop_tick(dev);
+
+ switch (reason) {
+ case MFC_REG_R2H_CMD_CACHE_FLUSH_RET:
+ case MFC_REG_R2H_CMD_SYS_INIT_RET:
+ case MFC_REG_R2H_CMD_FW_STATUS_RET:
+ case MFC_REG_R2H_CMD_SLEEP_RET:
+ case MFC_REG_R2H_CMD_WAKEUP_RET:
+ mfc_clear_int_sfr();
+ mfc_wake_up_dev(dev, reason, err);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int __mfc_irq_ctx(struct mfc_ctx *ctx, unsigned int reason, unsigned int err)
+{
+ struct mfc_dev *dev = ctx->dev;
+
+ switch (reason) {
+ case MFC_REG_R2H_CMD_ERR_RET:
+ if (ctx->otf_handle) {
+ mfc_otf_handle_error(ctx, reason, err);
+ break;
+ }
+ /* An error has occured */
+ if (ctx->state == MFCINST_RUNNING || ctx->state == MFCINST_ABORT) {
+ if ((mfc_get_err(err) >= MFC_REG_ERR_WARNINGS_START) &&
+ (mfc_get_err(err) <= MFC_REG_ERR_WARNINGS_END))
+ __mfc_handle_frame(ctx, reason, err);
+ else
+ __mfc_handle_frame_error(ctx, reason, err);
+ } else {
+ __mfc_handle_error(ctx, reason, err);
+ }
+ break;
+ case MFC_REG_R2H_CMD_SLICE_DONE_RET:
+ case MFC_REG_R2H_CMD_FIELD_DONE_RET:
+ case MFC_REG_R2H_CMD_FRAME_DONE_RET:
+ case MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET:
+ return __mfc_handle_done_frame(ctx, reason, err);
+ case MFC_REG_R2H_CMD_COMPLETE_SEQ_RET:
+ if (ctx->type == MFCINST_ENCODER) {
+ __mfc_handle_stream(ctx);
+ mfc_change_state(ctx, MFCINST_RUNNING);
+ } else if (ctx->type == MFCINST_DECODER) {
+ return __mfc_handle_done_frame(ctx, reason, err);
+ }
+ break;
+ case MFC_REG_R2H_CMD_SEQ_DONE_RET:
+ if (ctx->type == MFCINST_ENCODER) {
+ if (ctx->otf_handle) {
+ mfc_otf_handle_seq(ctx);
+ break;
+ }
+ __mfc_handle_seq_enc(ctx);
+ } else if (ctx->type == MFCINST_DECODER) {
+ __mfc_handle_seq_dec(ctx);
+ }
+ break;
+ case MFC_REG_R2H_CMD_OPEN_INSTANCE_RET:
+ ctx->inst_no = mfc_get_inst_no();
+ mfc_change_state(ctx, MFCINST_GOT_INST);
+ break;
+ case MFC_REG_R2H_CMD_CLOSE_INSTANCE_RET:
+ mfc_change_state(ctx, MFCINST_FREE);
+ break;
+ case MFC_REG_R2H_CMD_NAL_ABORT_RET:
+ __mfc_handle_nal_abort(ctx);
+ break;
+ case MFC_REG_R2H_CMD_DPB_FLUSH_RET:
+ mfc_change_state(ctx, MFCINST_ABORT);
+ break;
+ case MFC_REG_R2H_CMD_INIT_BUFFERS_RET:
+ if (err != 0) {
+ mfc_err_ctx("INIT_BUFFERS_RET error: %d\n", err);
+ break;
+ }
+
+ mfc_change_state(ctx, MFCINST_RUNNING);
+ if (ctx->type == MFCINST_DECODER) {
+ if (ctx->wait_state == WAIT_DECODING) {
+ ctx->wait_state = WAIT_INITBUF_DONE;
+ mfc_debug(2, "INIT_BUFFER has done, but can't start decoding\n");
+ }
+ if (ctx->is_dpb_realloc)
+ ctx->is_dpb_realloc = 0;
+ }
+ break;
+ default:
+ mfc_err_ctx("Unknown int reason: %d\n", reason);
+ }
+
+ return 1;
+}
+
+/* Interrupt processing */
+irqreturn_t mfc_irq(int irq, void *priv)
+{
+ struct mfc_dev *dev = priv;
+ struct mfc_ctx *ctx;
+ unsigned int reason;
+ unsigned int err;
+ int ret = -1;
+
+ mfc_debug_enter();
+
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ goto irq_end;
+ }
+
+ if (mfc_pm_get_pwr_ref_cnt(dev) == 0) {
+ mfc_err_dev("no mfc power on\n");
+ call_dop(dev, dump_and_stop_debug_mode, dev);
+ goto irq_end;
+ }
+
+ /* Get the reason of interrupt and the error code */
+ reason = mfc_get_int_reason();
+ err = mfc_get_int_err();
+ mfc_debug(1, "Int reason: %d (err: %d)\n", reason, err);
+ MFC_TRACE_DEV("<< INT: %d\n", reason);
+
+ dev->preempt_ctx = MFC_NO_INSTANCE_SET;
+
+ if (dbg_enable && (reason != MFC_REG_R2H_CMD_QUEUE_DONE_RET))
+ mfc_dbg_disable(dev);
+
+ if ((sfr_dump & MFC_DUMP_ERR_INT) && (reason == MFC_REG_R2H_CMD_ERR_RET))
+ call_dop(dev, dump_regs, dev);
+
+ if ((sfr_dump & MFC_DUMP_WARN_INT) &&
+ (err && (reason != MFC_REG_R2H_CMD_ERR_RET)))
+ call_dop(dev, dump_regs, dev);
+
+ if (is_err_condition(err))
+ call_dop(dev, dump_and_stop_debug_mode, dev);
+
+ if (dev->nal_q_handle) {
+ ret = __mfc_nal_q_irq(dev, reason, err);
+ if (ret == 0) {
+ mfc_debug(2, "[NALQ] command was handled\n");
+ goto irq_end;
+ } else if (ret == 1){
+ /* Path through */
+ mfc_debug(2, "NAL_START command will be handled\n");
+ } else {
+ mfc_debug(2, "[NALQ] command handling Error\n");
+ goto irq_end;
+ }
+ }
+
+ ret = __mfc_irq_dev(dev, reason, err);
+ if (!ret)
+ goto irq_end;
+
+ ctx = dev->ctx[dev->curr_ctx];
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ mfc_clear_int_sfr();
+ mfc_pm_clock_off(dev);
+ goto irq_end;
+ }
+
+ ret = __mfc_irq_ctx(ctx, reason, err);
+ if (!ret)
+ goto irq_end;
+
+ /* clean-up interrupt */
+ mfc_clear_int_sfr();
+
+ if ((ctx->state != MFCINST_RES_CHANGE_INIT) && (mfc_ctx_ready(ctx) == 0))
+ mfc_clear_bit(ctx->num, &dev->work_bits);
+
+ if (ctx->otf_handle) {
+ if (mfc_otf_ctx_ready(ctx))
+ mfc_set_bit(ctx->num, &dev->work_bits);
+ else
+ mfc_clear_bit(ctx->num, &dev->work_bits);
+ }
+
+ mfc_hwlock_handler_irq(dev, ctx, reason, err);
+
+irq_end:
+ mfc_debug_leave();
+ return IRQ_HANDLED;
+}
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_isr.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_ISR_H
+#define __MFC_ISR_H __FILE__
+
+#include <linux/interrupt.h>
+
+#include "mfc_common.h"
+
+#include "mfc_utils.h"
+
+irqreturn_t mfc_top_half_irq(int irq, void *priv);
+irqreturn_t mfc_irq(int irq, void *priv);
+
+static inline void mfc_handle_force_change_status(struct mfc_ctx *ctx)
+{
+ if (ctx->state != MFCINST_ABORT && ctx->state != MFCINST_HEAD_PARSED &&
+ ctx->state != MFCINST_RES_CHANGE_FLUSH)
+ mfc_change_state(ctx, MFCINST_RUNNING);
+}
+
+#endif /* __MFC_ISR_H */
#include "mfc_mmcache.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
static const unsigned char mmcache_SFR_0x0010[] = {
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
#include "mfc_sync.h"
#include "mfc_pm.h"
-#include "mfc_cal.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_qos.h"
#include "mfc_queue.h"
#include "mfc_opr.h"
#include "mfc_inst.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
#include "mfc_queue.h"
#include "mfc_utils.h"
#include "mfc_inst.h"
#include "mfc_pm.h"
#include "mfc_cmd.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
#include "mfc_qos.h"
#include "mfc_queue.h"
#include <linux/clk.h>
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
void mfc_perf_register(struct mfc_dev *dev);
void __mfc_measure_init(void);
#include "mfc_pm.h"
-#include "mfc_cal.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
void mfc_pm_init(struct mfc_dev *dev)
{
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_reg.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/delay.h>
-
-#include "mfc_reg.h"
-
-void mfc_dbg_enable(struct mfc_dev *dev)
-{
- mfc_debug(2, "MFC debug info enable\n");
- MFC_WRITEL(0x1, MFC_REG_DBG_INFO_ENABLE);
-}
-
-void mfc_dbg_disable(struct mfc_dev *dev)
-{
- mfc_debug(2, "MFC debug info disable\n");
- MFC_WRITEL(0x0, MFC_REG_DBG_INFO_ENABLE);
-}
-
-void mfc_dbg_set_addr(struct mfc_dev *dev)
-{
- struct mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
-
- memset((void *)dev->dbg_info_buf.vaddr, 0, buf_size->dbg_info_buf);
-
- MFC_WRITEL(dev->dbg_info_buf.daddr, MFC_REG_DBG_BUFFER_ADDR);
- MFC_WRITEL(buf_size->dbg_info_buf, MFC_REG_DBG_BUFFER_SIZE);
-}
-
-void mfc_otf_set_frame_addr(struct mfc_ctx *ctx, int num_planes)
-{
- struct mfc_dev *dev = ctx->dev;
- struct _otf_handle *handle = ctx->otf_handle;
- struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
- int index = handle->otf_buf_index;
- int i;
-
- for (i = 0; i < num_planes; i++) {
- mfc_debug(2, "[OTF][FRAME] set frame buffer[%d], 0x%08llx)\n",
- i, buf_addr->otf_daddr[index][i]);
- MFC_WRITEL(buf_addr->otf_daddr[index][i],
- MFC_REG_E_SOURCE_FIRST_ADDR + (i * 4));
- }
-}
-
-void mfc_otf_set_stream_size(struct mfc_ctx *ctx, unsigned int size)
-{
- struct mfc_dev *dev = ctx->dev;
- struct _otf_handle *handle = ctx->otf_handle;
- struct _otf_debug *debug = &handle->otf_debug;
- struct mfc_special_buf *buf;
-
- mfc_debug(2, "[OTF] set stream buffer full size, %u\n", size);
- MFC_WRITEL(size, MFC_REG_E_STREAM_BUFFER_SIZE);
-
- if (otf_dump && !ctx->is_drm) {
- buf = &debug->stream_buf[debug->frame_cnt];
- mfc_debug(2, "[OTF] set stream addr for debugging\n");
- mfc_debug(2, "[OTF][STREAM] buf[%d] daddr: 0x%08llx\n",
- debug->frame_cnt, buf->daddr);
- MFC_WRITEL(buf->daddr, MFC_REG_E_STREAM_BUFFER_ADDR);
- }
-}
-
-void mfc_otf_set_hwfc_index(struct mfc_ctx *ctx, int job_id)
-{
- struct mfc_dev *dev = ctx->dev;
-
- mfc_debug(2, "[OTF] set hwfc index, %d\n", job_id);
- HWFC_WRITEL(job_id, HWFC_ENCODING_IDX);
-}
-
-/* Set decoding frame buffer */
-int mfc_set_dec_codec_buffers(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- unsigned int i;
- size_t frame_size_mv;
- dma_addr_t buf_addr;
- int buf_size;
- int align_gap;
- struct mfc_raw_info *raw;
- unsigned int reg = 0;
-
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
-
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
-
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- raw = &ctx->raw_buf;
- buf_addr = ctx->codec_buf.daddr;
- buf_size = ctx->codec_buf.size;
-
- mfc_debug(2, "[MEMINFO] codec buf 0x%llx size: %d\n", buf_addr, buf_size);
- mfc_debug(2, "Total DPB COUNT: %d, display delay: %d\n",
- dec->total_dpb_count, dec->display_delay);
-
- /* set decoder DPB size, stride */
- MFC_WRITEL(dec->total_dpb_count, MFC_REG_D_NUM_DPB);
- for (i = 0; i < raw->num_planes; i++) {
- mfc_debug(2, "[FRAME] buf[%d] size: %d, stride: %d\n",
- i, raw->plane_size[i], raw->stride[i]);
- MFC_WRITEL(raw->plane_size[i], MFC_REG_D_FIRST_PLANE_DPB_SIZE + (i * 4));
- MFC_WRITEL(ctx->raw_buf.stride[i],
- MFC_REG_D_FIRST_PLANE_DPB_STRIDE_SIZE + (i * 4));
- if (ctx->is_10bit) {
- MFC_WRITEL(raw->stride_2bits[i], MFC_REG_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE + (i * 4));
- MFC_WRITEL(raw->plane_size_2bits[i], MFC_REG_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
- mfc_debug(2, "[FRAME][10BIT] 2bits buf[%d] size: %d, stride: %d\n",
- i, raw->plane_size_2bits[i], raw->stride_2bits[i]);
- }
- }
-
- /* set codec buffers */
- MFC_WRITEL(buf_addr, MFC_REG_D_SCRATCH_BUFFER_ADDR);
- MFC_WRITEL(ctx->scratch_buf_size, MFC_REG_D_SCRATCH_BUFFER_SIZE);
- buf_addr += ctx->scratch_buf_size;
- buf_size -= ctx->scratch_buf_size;
-
- if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx))
- MFC_WRITEL(ctx->mv_size, MFC_REG_D_MV_BUFFER_SIZE);
-
- if (IS_VP9_DEC(ctx)){
- MFC_WRITEL(buf_addr, MFC_REG_D_STATIC_BUFFER_ADDR);
- MFC_WRITEL(DEC_STATIC_BUFFER_SIZE, MFC_REG_D_STATIC_BUFFER_SIZE);
- buf_addr += DEC_STATIC_BUFFER_SIZE;
- buf_size -= DEC_STATIC_BUFFER_SIZE;
- }
-
- if (IS_MPEG4_DEC(ctx) && dec->loop_filter_mpeg4) {
- mfc_debug(2, "Add DPB for loop filter of MPEG4\n");
- for (i = 0; i < NUM_MPEG4_LF_BUF; i++) {
- MFC_WRITEL(buf_addr, MFC_REG_D_POST_FILTER_LUMA_DPB0 + (4 * i));
- buf_addr += ctx->loopfilter_luma_size;
- buf_size -= ctx->loopfilter_luma_size;
-
- MFC_WRITEL(buf_addr, MFC_REG_D_POST_FILTER_CHROMA_DPB0 + (4 * i));
- buf_addr += ctx->loopfilter_chroma_size;
- buf_size -= ctx->loopfilter_chroma_size;
- }
- reg |= ((dec->loop_filter_mpeg4 & MFC_REG_D_INIT_BUF_OPT_LF_CTRL_MASK)
- << MFC_REG_D_INIT_BUF_OPT_LF_CTRL_SHIFT);
- }
-
- reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT);
-
- if (CODEC_NOT_CODED(ctx)) {
- reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT);
- mfc_debug(2, "Notcoded frame copy mode start\n");
- }
- /* Enable 10bit Dithering */
- if (ctx->is_10bit) {
- reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_DITHERING_EN_SHIFT);
- /* 64byte align, It is vaid only for VP9 */
- reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
- } else {
- /* 16byte align, It is vaid only for VP9 */
- reg &= ~(0x1 << MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
- }
-
- MFC_WRITEL(reg, MFC_REG_D_INIT_BUFFER_OPTIONS);
-
- frame_size_mv = ctx->mv_size;
- MFC_WRITEL(dec->mv_count, MFC_REG_D_NUM_MV);
- if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx)) {
- for (i = 0; i < dec->mv_count; i++) {
- /* To test alignment */
- align_gap = buf_addr;
- buf_addr = ALIGN(buf_addr, 16);
- align_gap = buf_addr - align_gap;
- buf_size -= align_gap;
-
- MFC_WRITEL(buf_addr, MFC_REG_D_MV_BUFFER0 + i * 4);
- buf_addr += frame_size_mv;
- buf_size -= frame_size_mv;
- }
- }
-
- mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
- if (buf_size < 0) {
- mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/* Set encoding ref & codec buffer */
-int mfc_set_enc_codec_buffers(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_enc *enc = ctx->enc_priv;
- dma_addr_t buf_addr;
- int buf_size;
- int i;
-
- mfc_debug_enter();
-
- buf_addr = ctx->codec_buf.daddr;
- buf_size = ctx->codec_buf.size;
-
- mfc_debug(2, "[MEMINFO] codec buf 0x%llx, size: %d\n", buf_addr, buf_size);
- mfc_debug(2, "DPB COUNT: %d\n", ctx->dpb_count);
-
- MFC_WRITEL(buf_addr, MFC_REG_E_SCRATCH_BUFFER_ADDR);
- MFC_WRITEL(ctx->scratch_buf_size, MFC_REG_E_SCRATCH_BUFFER_SIZE);
- buf_addr += ctx->scratch_buf_size;
- buf_size -= ctx->scratch_buf_size;
-
- /* start address of per buffer is aligned */
- for (i = 0; i < ctx->dpb_count; i++) {
- MFC_WRITEL(buf_addr, MFC_REG_E_LUMA_DPB + (4 * i));
- buf_addr += enc->luma_dpb_size;
- buf_size -= enc->luma_dpb_size;
- }
- for (i = 0; i < ctx->dpb_count; i++) {
- MFC_WRITEL(buf_addr, MFC_REG_E_CHROMA_DPB + (4 * i));
- buf_addr += enc->chroma_dpb_size;
- buf_size -= enc->chroma_dpb_size;
- }
- for (i = 0; i < ctx->dpb_count; i++) {
- MFC_WRITEL(buf_addr, MFC_REG_E_ME_BUFFER + (4 * i));
- buf_addr += enc->me_buffer_size;
- buf_size -= enc->me_buffer_size;
- }
-
- MFC_WRITEL(buf_addr, MFC_REG_E_TMV_BUFFER0);
- buf_addr += enc->tmv_buffer_size >> 1;
- MFC_WRITEL(buf_addr, MFC_REG_E_TMV_BUFFER1);
- buf_addr += enc->tmv_buffer_size >> 1;
- buf_size -= enc->tmv_buffer_size;
-
- mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
- if (buf_size < 0) {
- mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
- return -ENOMEM;
- }
-
- mfc_debug_leave();
-
- return 0;
-}
-
-/* Set registers for decoding stream buffer */
-int mfc_set_dec_stream_buffer(struct mfc_ctx *ctx, struct mfc_buf *mfc_buf,
- unsigned int start_num_byte, unsigned int strm_size)
-{
- struct mfc_dev *dev;
- struct mfc_dec *dec;
- unsigned int cpb_buf_size;
- dma_addr_t addr;
- int index = -1;
-
- mfc_debug_enter();
- if (!ctx) {
- mfc_err_dev("no mfc context to run\n");
- return -EINVAL;
- }
- dev = ctx->dev;
- if (!dev) {
- mfc_err_dev("no mfc device to run\n");
- return -EINVAL;
- }
- dec = ctx->dec_priv;
- if (!dec) {
- mfc_err_dev("no mfc decoder to run\n");
- return -EINVAL;
- }
-
- cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN);
-
- if (mfc_buf) {
- index = mfc_buf->vb.vb2_buf.index;
- addr = mfc_buf->addr[0][0];
- if (strm_size > set_strm_size_max(cpb_buf_size)) {
- mfc_info_ctx("Decrease strm_size because of %d align: %u -> %u\n",
- STREAM_BUF_ALIGN, strm_size, set_strm_size_max(cpb_buf_size));
- strm_size = set_strm_size_max(cpb_buf_size);
- mfc_buf->vb.vb2_buf.planes[0].bytesused = strm_size;
- }
- } else {
- addr = 0;
- }
-
- mfc_debug(2, "[BUFINFO] ctx[%d] set src index: %d, addr: 0x%08llx\n",
- ctx->num, index, addr);
- mfc_debug(2, "[STREAM] strm_size: %#lx(%d), buf_size: %u, offset: %u\n",
- strm_size, strm_size, cpb_buf_size, start_num_byte);
-
- if (strm_size == 0)
- mfc_info_ctx("stream size is 0\n");
-
- MFC_WRITEL(strm_size, MFC_REG_D_STREAM_DATA_SIZE);
- MFC_WRITEL(addr, MFC_REG_D_CPB_BUFFER_ADDR);
- MFC_WRITEL(cpb_buf_size, MFC_REG_D_CPB_BUFFER_SIZE);
- MFC_WRITEL(start_num_byte, MFC_REG_D_CPB_BUFFER_OFFSET);
-
- if (mfc_buf)
- MFC_TRACE_CTX("Set src[%d] fd: %d, %#llx\n",
- index, mfc_buf->vb.vb2_buf.planes[0].m.fd, addr);
-
- mfc_debug_leave();
- return 0;
-}
-
-void mfc_set_enc_frame_buffer(struct mfc_ctx *ctx,
- struct mfc_buf *mfc_buf, int num_planes)
-{
- struct mfc_dev *dev = ctx->dev;
- dma_addr_t addr[3] = { 0, 0, 0 };
- dma_addr_t addr_2bit[2] = { 0, 0 };
- int index, i;
-
- if (!mfc_buf) {
- mfc_debug(3, "enc zero buffer set\n");
- goto buffer_set;
- }
-
- index = mfc_buf->vb.vb2_buf.index;
- if (mfc_buf->num_valid_bufs > 0) {
- for (i = 0; i < num_planes; i++) {
- addr[i] = mfc_buf->addr[mfc_buf->next_index][i];
- mfc_debug(2, "[BUFCON][BUFINFO] ctx[%d] set src index:%d, batch[%d], addr[%d]: 0x%08llx\n",
- ctx->num, index, mfc_buf->next_index, i, addr[i]);
- }
- mfc_buf->next_index++;
- } else {
- for (i = 0; i < num_planes; i++) {
- addr[i] = mfc_buf->addr[0][i];
- mfc_debug(2, "[BUFINFO] ctx[%d] set src index:%d, addr[%d]: 0x%08llx\n",
- ctx->num, index, i, addr[i]);
- }
- }
-
-buffer_set:
- for (i = 0; i < num_planes; i++)
- MFC_WRITEL(addr[i], MFC_REG_E_SOURCE_FIRST_ADDR + (i * 4));
-
- if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M_S10B ||
- ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M_S10B) {
- addr_2bit[0] = addr[0] + NV12N_10B_Y_8B_SIZE(ctx->img_width, ctx->img_height);
- addr_2bit[1] = addr[1] + NV12N_10B_CBCR_8B_SIZE(ctx->img_width, ctx->img_height);
-
- for (i = 0; i < num_planes; i++) {
- MFC_WRITEL(addr_2bit[i], MFC_REG_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
- mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
- ctx->num, i, addr_2bit[i]);
- }
- } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV16M_S10B ||
- ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV61M_S10B) {
- addr_2bit[0] = addr[0] + NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
- addr_2bit[1] = addr[1] + NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-
- for (i = 0; i < num_planes; i++) {
- MFC_WRITEL(addr_2bit[i], MFC_REG_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
- mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
- ctx->num, i, addr_2bit[i]);
- }
- }
-}
-
-/* Set registers for encoding stream buffer */
-int mfc_set_enc_stream_buffer(struct mfc_ctx *ctx,
- struct mfc_buf *mfc_buf)
-{
- struct mfc_dev *dev = ctx->dev;
- dma_addr_t addr;
- unsigned int size, offset, index;
-
- index = mfc_buf->vb.vb2_buf.index;
- addr = mfc_buf->addr[0][0];
- offset = mfc_buf->vb.vb2_buf.planes[0].data_offset;
- size = (unsigned int)vb2_plane_size(&mfc_buf->vb.vb2_buf, 0);
- size = ALIGN(size, 512);
-
- MFC_WRITEL(addr, MFC_REG_E_STREAM_BUFFER_ADDR); /* 16B align */
- MFC_WRITEL(size, MFC_REG_E_STREAM_BUFFER_SIZE);
- MFC_WRITEL(offset, MFC_REG_E_STREAM_BUFFER_OFFSET);
-
- mfc_debug(2, "[BUFINFO] ctx[%d] set dst index: %d, addr: 0x%08llx\n",
- ctx->num, index, addr);
- mfc_debug(2, "[STREAM] buf_size: %u, offset: %d\n", size, offset);
-
- return 0;
-}
-
-void mfc_get_enc_frame_buffer(struct mfc_ctx *ctx,
- dma_addr_t addr[], int num_planes)
-{
- struct mfc_dev *dev = ctx->dev;
- unsigned long enc_recon_y_addr, enc_recon_c_addr;
- int i, addr_offset;
-
- addr_offset = MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR;
-
- for (i = 0; i < num_planes; i++)
- addr[i] = MFC_READL(addr_offset + (i * 4));
-
- enc_recon_y_addr = MFC_READL(MFC_REG_E_RECON_LUMA_DPB_ADDR);
- enc_recon_c_addr = MFC_READL(MFC_REG_E_RECON_CHROMA_DPB_ADDR);
-
- mfc_debug(2, "[MEMINFO] recon y: 0x%08lx c: 0x%08lx\n",
- enc_recon_y_addr, enc_recon_c_addr);
-}
-
-void mfc_set_enc_stride(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- int i;
-
- for (i = 0; i < ctx->raw_buf.num_planes; i++) {
- MFC_WRITEL(ctx->raw_buf.stride[i],
- MFC_REG_E_SOURCE_FIRST_STRIDE + (i * 4));
- mfc_debug(2, "[FRAME] enc src plane[%d] stride: %d\n",
- i, ctx->raw_buf.stride[i]);
- }
-}
-
-int mfc_set_dynamic_dpb(struct mfc_ctx *ctx, struct mfc_buf *dst_mb)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- struct mfc_raw_info *raw = &ctx->raw_buf;
- int dst_index;
- int i;
-
- dst_index = dst_mb->vb.vb2_buf.index;
- set_bit(dst_index, &dec->available_dpb);
- dec->dynamic_set = 1 << dst_index;
- mfc_debug(2, "[DPB] ADDING Flag after: 0x%lx\n", dec->available_dpb);
-
- /* for debugging about black bar detection */
- if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar) {
- for (i = 0; i < raw->num_planes; i++) {
- dec->frame_vaddr[i][dec->frame_cnt] = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, i);
- dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[0][i];
- dec->frame_size[i][dec->frame_cnt] = raw->plane_size[i];
- dec->index[i][dec->frame_cnt] = dst_index;
- dec->fd[i][dec->frame_cnt] = dst_mb->vb.vb2_buf.planes[0].m.fd;
- }
- dec->frame_cnt++;
- if (dec->frame_cnt >= 30)
- dec->frame_cnt = 0;
- }
-
- /* decoder dst buffer CFW PROT */
- mfc_protect_dpb(ctx, dst_mb);
-
- for (i = 0; i < raw->num_planes; i++) {
- MFC_WRITEL(raw->plane_size[i],
- MFC_REG_D_FIRST_PLANE_DPB_SIZE + i * 4);
- MFC_WRITEL(dst_mb->addr[0][i],
- MFC_REG_D_FIRST_PLANE_DPB0 + (i * 0x100 + dst_index * 4));
- if (ctx->is_10bit)
- MFC_WRITEL(raw->plane_size_2bits[i],
- MFC_REG_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
- mfc_debug(2, "[BUFINFO][DPB] ctx[%d] set dst index: %d, addr[%d]: 0x%08llx\n",
- ctx->num, dst_index, i, dst_mb->addr[0][i]);
- }
-
- MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
- dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0],
- dec->available_dpb, dec->dynamic_used);
-
- return 0;
-}
-
-void mfc_set_pixel_format(struct mfc_dev *dev, unsigned int format)
-{
- unsigned int reg = 0;
- unsigned int pix_val, mem_type_10bit = 0;
-
- if (dev->pdata->P010_decoding)
- mem_type_10bit = 1;
-
- switch (format) {
- case V4L2_PIX_FMT_NV12M:
- case V4L2_PIX_FMT_NV12N:
- case V4L2_PIX_FMT_NV12MT_16X16:
- case V4L2_PIX_FMT_NV16M:
- pix_val = 0;
- break;
- case V4L2_PIX_FMT_NV21M:
- case V4L2_PIX_FMT_NV61M:
- pix_val = 1;
- break;
- case V4L2_PIX_FMT_YVU420M:
- pix_val = 2;
- break;
- case V4L2_PIX_FMT_YUV420M:
- case V4L2_PIX_FMT_YUV420N:
- pix_val = 3;
- break;
- /* For 10bit direct set */
- case V4L2_PIX_FMT_NV12N_10B:
- case V4L2_PIX_FMT_NV12M_S10B:
- case V4L2_PIX_FMT_NV16M_S10B:
- mem_type_10bit = 0;
- pix_val = 0;
- break;
- case V4L2_PIX_FMT_NV12M_P010:
- case V4L2_PIX_FMT_NV16M_P210:
- mem_type_10bit = 1;
- pix_val = 0;
- break;
- case V4L2_PIX_FMT_NV21M_S10B:
- case V4L2_PIX_FMT_NV61M_S10B:
- mem_type_10bit = 0;
- pix_val = 1;
- break;
- case V4L2_PIX_FMT_NV21M_P010:
- case V4L2_PIX_FMT_NV61M_P210:
- mem_type_10bit = 1;
- pix_val = 1;
- break;
- default:
- pix_val = 0;
- break;
- }
- reg |= pix_val;
- reg |= (mem_type_10bit << 4);
- MFC_WRITEL(reg, MFC_REG_PIXEL_FORMAT);
- mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit for 10bit: %d (reg: %#x)\n",
- pix_val, mem_type_10bit, reg);
-}
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/mfc_reg.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MFC_REG_H
-#define __MFC_REG_H __FILE__
-
-#include "mfc_common.h"
-
-#include "mfc_utils.h"
-
-#define MFC_READL(offset) readl(dev->regs_base + (offset))
-#define MFC_WRITEL(data, offset) writel((data), dev->regs_base + (offset))
-
-#define MFC_MMU0_READL(offset) readl(dev->sysmmu0_base + (offset))
-#define MFC_MMU1_READL(offset) readl(dev->sysmmu1_base + (offset))
-
-#define HWFC_WRITEL(data, offset) writel((data), dev->hwfc_base + (offset))
-
-#define MMCACHE_READL(offset) readl(dev->mmcache.base + (offset))
-#define MMCACHE_WRITEL(data, offset) writel((data), dev->mmcache.base + (offset))
-
-/* version */
-#define mfc_get_fimv_info() ((MFC_READL(MFC_REG_FW_VERSION) \
- >> MFC_REG_FW_VER_INFO_SHFT) \
- & MFC_REG_FW_VER_INFO_MASK)
-#define mfc_get_fw_ver_year() ((MFC_READL(MFC_REG_FW_VERSION) \
- >> MFC_REG_FW_VER_YEAR_SHFT) \
- & MFC_REG_FW_VER_YEAR_MASK)
-#define mfc_get_fw_ver_month() ((MFC_READL(MFC_REG_FW_VERSION) \
- >> MFC_REG_FW_VER_MONTH_SHFT) \
- & MFC_REG_FW_VER_MONTH_MASK)
-#define mfc_get_fw_ver_date() ((MFC_READL(MFC_REG_FW_VERSION) \
- >> MFC_REG_FW_VER_DATE_SHFT) \
- & MFC_REG_FW_VER_DATE_MASK)
-#define mfc_get_fw_ver_all() ((MFC_READL(MFC_REG_FW_VERSION) \
- >> MFC_REG_FW_VER_ALL_SHFT) \
- & MFC_REG_FW_VER_ALL_MASK)
-#define mfc_get_mfc_version() ((MFC_READL(MFC_REG_MFC_VERSION) \
- >> MFC_REG_MFC_VER_SHFT) \
- & MFC_REG_MFC_VER_MASK)
-
-
-/* decoding & display information */
-#define mfc_get_dec_status() (MFC_READL(MFC_REG_D_DECODED_STATUS) \
- & MFC_REG_DEC_STATUS_DECODED_STATUS_MASK)
-#define mfc_get_disp_status() (MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
- & MFC_REG_DISP_STATUS_DISPLAY_STATUS_MASK)
-#define mfc_get_res_change() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
- >> MFC_REG_DISP_STATUS_RES_CHANGE_SHIFT) \
- & MFC_REG_DISP_STATUS_RES_CHANGE_MASK)
-#define mfc_get_black_bar_detection() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
- >> MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_SHIFT) \
- & MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_MASK)
-#define mfc_get_dpb_change() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
- >> MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_SHIFT) \
- & MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_MASK)
-#define mfc_get_scratch_change() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
- >> MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT) \
- & MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK)
-#define mfc_get_disp_frame_type() (MFC_READL(MFC_REG_D_DISPLAY_FRAME_TYPE) \
- & MFC_REG_DISPLAY_FRAME_MASK)
-#define mfc_get_dec_frame_type() (MFC_READL(MFC_REG_D_DECODED_FRAME_TYPE) \
- & MFC_REG_DECODED_FRAME_MASK)
-#define mfc_get_interlace_type() ((MFC_READL(MFC_REG_D_DISPLAY_FRAME_TYPE) \
- >> MFC_REG_DISPLAY_TEMP_INFO_SHIFT) \
- & MFC_REG_DISPLAY_TEMP_INFO_MASK)
-#define mfc_is_interlace_picture() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
- >> MFC_REG_DISP_STATUS_INTERLACE_SHIFT)\
- & MFC_REG_DISP_STATUS_INTERLACE_MASK)
-#define mfc_is_mbaff_picture() ((MFC_READL(MFC_REG_D_H264_INFO) \
- >> MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT)\
- & MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_MASK)
-#define mfc_get_img_width() MFC_READL(MFC_REG_D_DISPLAY_FRAME_WIDTH)
-#define mfc_get_img_height() MFC_READL(MFC_REG_D_DISPLAY_FRAME_HEIGHT)
-#define mfc_get_disp_y_addr() MFC_READL(MFC_REG_D_DISPLAY_LUMA_ADDR)
-#define mfc_get_dec_y_addr() MFC_READL(MFC_REG_D_DECODED_LUMA_ADDR)
-
-
-/* kind of interrupt */
-#define mfc_get_int_err() MFC_READL(MFC_REG_ERROR_CODE)
-#define mfc_get_err(x) (((x) >> MFC_REG_ERR_STATUS_SHIFT) \
- & MFC_REG_ERR_STATUS_MASK)
-#define mfc_get_warn(x) (((x) >> MFC_REG_WARN_STATUS_SHIFT) \
- & MFC_REG_WARN_STATUS_MASK)
-
-
-/* additional information */
-#define mfc_get_consumed_stream() MFC_READL(MFC_REG_D_DECODED_NAL_SIZE)
-#define mfc_get_dpb_count() MFC_READL(MFC_REG_D_MIN_NUM_DPB)
-#define mfc_get_min_dpb_size(x) MFC_READL(MFC_REG_D_MIN_FIRST_PLANE_DPB_SIZE + (x * 4))
-#define mfc_get_scratch_size() MFC_READL(MFC_REG_D_MIN_SCRATCH_BUFFER_SIZE)
-#define mfc_get_mv_count() MFC_READL(MFC_REG_D_MIN_NUM_MV)
-#define mfc_get_inst_no() MFC_READL(MFC_REG_RET_INSTANCE_ID)
-#define mfc_get_enc_dpb_count() MFC_READL(MFC_REG_E_NUM_DPB)
-#define mfc_get_enc_scratch_size() MFC_READL(MFC_REG_E_MIN_SCRATCH_BUFFER_SIZE)
-#define mfc_get_enc_strm_size() MFC_READL(MFC_REG_E_STREAM_SIZE)
-#define mfc_get_enc_slice_type() MFC_READL(MFC_REG_E_SLICE_TYPE)
-#define mfc_get_enc_pic_count() MFC_READL(MFC_REG_E_PICTURE_COUNT)
-#define mfc_get_sei_avail() MFC_READL(MFC_REG_D_SEI_AVAIL)
-#define mfc_get_sei_content_light() MFC_READL(MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI)
-#define mfc_get_sei_mastering0() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0)
-#define mfc_get_sei_mastering1() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1)
-#define mfc_get_sei_mastering2() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2)
-#define mfc_get_sei_mastering3() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3)
-#define mfc_get_sei_mastering4() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4)
-#define mfc_get_sei_mastering5() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5)
-#define mfc_get_sei_avail_frame_pack() (MFC_READL(MFC_REG_D_SEI_AVAIL) \
- & MFC_REG_D_SEI_AVAIL_FRAME_PACK_MASK)
-#define mfc_get_sei_avail_content_light() ((MFC_READL(MFC_REG_D_SEI_AVAIL) \
- >> MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT) \
- & MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_MASK)
-#define mfc_get_sei_avail_mastering_display() ((MFC_READL(MFC_REG_D_SEI_AVAIL) \
- >> MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT) \
- & MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK)
-#define mfc_get_video_signal_type() ((MFC_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
- >> MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT) \
- & MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_MASK)
-#define mfc_get_colour_description() ((MFC_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
- >> MFC_REG_D_COLOUR_DESCRIPTION_FLAG_SHIFT) \
- & MFC_REG_D_COLOUR_DESCRIPTION_FLAG_MASK)
-#define mfc_get_black_bar_pos_x() ((MFC_READL(MFC_REG_D_BLACK_BAR_START_POS) \
- >> MFC_REG_D_BLACK_BAR_START_X_SHIFT) \
- & MFC_REG_D_BLACK_BAR_START_X_MASK)
-#define mfc_get_black_bar_pos_y() ((MFC_READL(MFC_REG_D_BLACK_BAR_START_POS) \
- >> MFC_REG_D_BLACK_BAR_START_Y_SHIFT) \
- & MFC_REG_D_BLACK_BAR_START_Y_MASK)
-#define mfc_get_black_bar_image_w() ((MFC_READL(MFC_REG_D_BLACK_BAR_IMAGE_SIZE) \
- >> MFC_REG_D_BLACK_BAR_IMAGE_W_SHIFT) \
- & MFC_REG_D_BLACK_BAR_IMAGE_W_MASK)
-#define mfc_get_black_bar_image_h() ((MFC_READL(MFC_REG_D_BLACK_BAR_IMAGE_SIZE) \
- >> MFC_REG_D_BLACK_BAR_IMAGE_H_SHIFT) \
- & MFC_REG_D_BLACK_BAR_IMAGE_H_MASK)
-#define mfc_get_mvc_disp_view_id() (MFC_READL(MFC_REG_D_MVC_VIEW_ID) \
- & MFC_REG_D_MVC_VIEW_ID_DISP_MASK)
-#define mfc_get_profile() (MFC_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
- & MFC_REG_D_DECODED_PIC_PROFILE_MASK)
-#define mfc_get_luma_bit_depth_minus8() ((MFC_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
- >> MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_SHIFT) \
- & MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_MASK)
-#define mfc_get_chroma_bit_depth_minus8() ((MFC_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
- >> MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT) \
- & MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_MASK)
-#define mfc_get_dec_used_flag() MFC_READL(MFC_REG_D_USED_DPB_FLAG_LOWER)
-#define mfc_get_enc_nal_done_info() ((MFC_READL(MFC_REG_E_NAL_DONE_INFO) & (0x3 << 4)) >> 4)
-#define mfc_get_chroma_format() (MFC_READL(MFC_REG_D_CHROMA_FORMAT) \
- & MFC_REG_D_CHROMA_FORMAT_MASK)
-#define mfc_get_color_range() ((MFC_READL(MFC_REG_D_CHROMA_FORMAT) \
- >> MFC_REG_D_COLOR_RANGE_SHIFT) \
- & MFC_REG_D_COLOR_RANGE_MASK)
-#define mfc_get_color_space() ((MFC_READL(MFC_REG_D_CHROMA_FORMAT) \
- >> MFC_REG_D_COLOR_SPACE_SHIFT) \
- & MFC_REG_D_COLOR_SPACE_MASK)
-#define mfc_get_num_of_tile() ((MFC_READL(MFC_REG_D_DECODED_STATUS) \
- >> MFC_REG_DEC_STATUS_NUM_OF_TILE_SHIFT) \
- & MFC_REG_DEC_STATUS_NUM_OF_TILE_MASK)
-
-
-/* nal queue information */
-#define mfc_get_nal_q_input_count() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_COUNT)
-#define mfc_get_nal_q_output_count() MFC_READL(MFC_REG_NAL_QUEUE_OUTPUT_COUNT)
-#define mfc_get_nal_q_input_exe_count() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT)
-#define mfc_get_nal_q_info() MFC_READL(MFC_REG_NAL_QUEUE_INFO)
-#define mfc_get_nal_q_input_addr() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_ADDR)
-#define mfc_get_nal_q_input_size() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_SIZE)
-#define mfc_get_nal_q_output_addr() MFC_READL(MFC_REG_NAL_QUEUE_OUTPUT_ADDR)
-#define mfc_get_nal_q_output_ize() MFC_READL(MFC_REG_NAL_QUEUE_OUTPUT_SIZE)
-
-static inline void mfc_reset_nal_queue_registers(struct mfc_dev *dev)
-{
- MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_INPUT_COUNT);
- MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_OUTPUT_COUNT);
- MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT);
- MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_INFO);
-}
-
-static inline void mfc_update_nal_queue_input(struct mfc_dev *dev,
- dma_addr_t addr, unsigned int size)
-{
- MFC_WRITEL(addr, MFC_REG_NAL_QUEUE_INPUT_ADDR);
- MFC_WRITEL(size, MFC_REG_NAL_QUEUE_INPUT_SIZE);
-}
-
-static inline void mfc_update_nal_queue_output(struct mfc_dev *dev,
- dma_addr_t addr, unsigned int size)
-{
- MFC_WRITEL(addr, MFC_REG_NAL_QUEUE_OUTPUT_ADDR);
- MFC_WRITEL(size, MFC_REG_NAL_QUEUE_OUTPUT_SIZE);
-}
-
-static inline void mfc_update_nal_queue_input_count(struct mfc_dev *dev,
- unsigned int input_count)
-{
- MFC_WRITEL(input_count, MFC_REG_NAL_QUEUE_INPUT_COUNT);
-}
-
-static inline void mfc_dec_store_crop_info(struct mfc_ctx *ctx)
-{
- struct mfc_dev *dev = ctx->dev;
- struct mfc_dec *dec = ctx->dec_priv;
- u32 left, right, top, bottom;
-
- left = MFC_READL(MFC_REG_D_DISPLAY_CROP_INFO1);
- right = left >> MFC_REG_D_SHARED_CROP_RIGHT_SHIFT;
- left = left & MFC_REG_D_SHARED_CROP_LEFT_MASK;
- top = MFC_READL(MFC_REG_D_DISPLAY_CROP_INFO2);
- bottom = top >> MFC_REG_D_SHARED_CROP_BOTTOM_SHIFT;
- top = top & MFC_REG_D_SHARED_CROP_TOP_MASK;
-
- dec->cr_left = left;
- dec->cr_right = right;
- dec->cr_top = top;
- dec->cr_bot = bottom;
-}
-
-static inline void mfc_clear_enc_res_change(struct mfc_dev *dev)
-{
- unsigned int reg = 0;
-
- reg = MFC_READL(MFC_REG_E_PARAM_CHANGE);
- reg &= ~(0x7 << 6);
- MFC_WRITEL(reg, MFC_REG_E_PARAM_CHANGE);
-}
-
-static inline void mfc_clear_roi_enable(struct mfc_dev *dev)
-{
- unsigned int reg = 0;
-
- reg = MFC_READL(MFC_REG_E_RC_ROI_CTRL);
- reg &= ~(0x1);
- MFC_WRITEL(reg, MFC_REG_E_RC_ROI_CTRL);
-}
-
-void mfc_dbg_enable(struct mfc_dev *dev);
-void mfc_dbg_disable(struct mfc_dev *dev);
-void mfc_dbg_set_addr(struct mfc_dev *dev);
-
-void mfc_otf_set_frame_addr(struct mfc_ctx *ctx, int num_planes);
-void mfc_otf_set_stream_size(struct mfc_ctx *ctx, unsigned int size);
-void mfc_otf_set_hwfc_index(struct mfc_ctx *ctx, int job_id);
-
-int mfc_set_dec_codec_buffers(struct mfc_ctx *ctx);
-int mfc_set_enc_codec_buffers(struct mfc_ctx *mfc_ctx);
-
-int mfc_set_dec_stream_buffer(struct mfc_ctx *ctx,
- struct mfc_buf *mfc_buf,
- unsigned int start_num_byte,
- unsigned int buf_size);
-
-void mfc_set_enc_frame_buffer(struct mfc_ctx *ctx,
- struct mfc_buf *mfc_buf, int num_planes);
-int mfc_set_enc_stream_buffer(struct mfc_ctx *ctx,
- struct mfc_buf *mfc_buf);
-
-void mfc_get_enc_frame_buffer(struct mfc_ctx *ctx,
- dma_addr_t addr[], int num_planes);
-void mfc_set_enc_stride(struct mfc_ctx *ctx);
-
-int mfc_set_dynamic_dpb(struct mfc_ctx *ctx, struct mfc_buf *dst_vb);
-
-void mfc_set_pixel_format(struct mfc_dev *dev, unsigned int format);
-
-#endif /* __MFC_REG_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_reg.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+
+#include "mfc_reg_api.h"
+
+void mfc_dbg_enable(struct mfc_dev *dev)
+{
+ mfc_debug(2, "MFC debug info enable\n");
+ MFC_WRITEL(0x1, MFC_REG_DBG_INFO_ENABLE);
+}
+
+void mfc_dbg_disable(struct mfc_dev *dev)
+{
+ mfc_debug(2, "MFC debug info disable\n");
+ MFC_WRITEL(0x0, MFC_REG_DBG_INFO_ENABLE);
+}
+
+void mfc_dbg_set_addr(struct mfc_dev *dev)
+{
+ struct mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
+
+ memset((void *)dev->dbg_info_buf.vaddr, 0, buf_size->dbg_info_buf);
+
+ MFC_WRITEL(dev->dbg_info_buf.daddr, MFC_REG_DBG_BUFFER_ADDR);
+ MFC_WRITEL(buf_size->dbg_info_buf, MFC_REG_DBG_BUFFER_SIZE);
+}
+
+void mfc_otf_set_frame_addr(struct mfc_ctx *ctx, int num_planes)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct _otf_handle *handle = ctx->otf_handle;
+ struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
+ int index = handle->otf_buf_index;
+ int i;
+
+ for (i = 0; i < num_planes; i++) {
+ mfc_debug(2, "[OTF][FRAME] set frame buffer[%d], 0x%08llx)\n",
+ i, buf_addr->otf_daddr[index][i]);
+ MFC_WRITEL(buf_addr->otf_daddr[index][i],
+ MFC_REG_E_SOURCE_FIRST_ADDR + (i * 4));
+ }
+}
+
+void mfc_otf_set_stream_size(struct mfc_ctx *ctx, unsigned int size)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct _otf_handle *handle = ctx->otf_handle;
+ struct _otf_debug *debug = &handle->otf_debug;
+ struct mfc_special_buf *buf;
+
+ mfc_debug(2, "[OTF] set stream buffer full size, %u\n", size);
+ MFC_WRITEL(size, MFC_REG_E_STREAM_BUFFER_SIZE);
+
+ if (otf_dump && !ctx->is_drm) {
+ buf = &debug->stream_buf[debug->frame_cnt];
+ mfc_debug(2, "[OTF] set stream addr for debugging\n");
+ mfc_debug(2, "[OTF][STREAM] buf[%d] daddr: 0x%08llx\n",
+ debug->frame_cnt, buf->daddr);
+ MFC_WRITEL(buf->daddr, MFC_REG_E_STREAM_BUFFER_ADDR);
+ }
+}
+
+void mfc_otf_set_hwfc_index(struct mfc_ctx *ctx, int job_id)
+{
+ struct mfc_dev *dev = ctx->dev;
+
+ mfc_debug(2, "[OTF] set hwfc index, %d\n", job_id);
+ HWFC_WRITEL(job_id, HWFC_ENCODING_IDX);
+}
+
+/* Set decoding frame buffer */
+int mfc_set_dec_codec_buffers(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ unsigned int i;
+ size_t frame_size_mv;
+ dma_addr_t buf_addr;
+ int buf_size;
+ int align_gap;
+ struct mfc_raw_info *raw;
+ unsigned int reg = 0;
+
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ raw = &ctx->raw_buf;
+ buf_addr = ctx->codec_buf.daddr;
+ buf_size = ctx->codec_buf.size;
+
+ mfc_debug(2, "[MEMINFO] codec buf 0x%llx size: %d\n", buf_addr, buf_size);
+ mfc_debug(2, "Total DPB COUNT: %d, display delay: %d\n",
+ dec->total_dpb_count, dec->display_delay);
+
+ /* set decoder DPB size, stride */
+ MFC_WRITEL(dec->total_dpb_count, MFC_REG_D_NUM_DPB);
+ for (i = 0; i < raw->num_planes; i++) {
+ mfc_debug(2, "[FRAME] buf[%d] size: %d, stride: %d\n",
+ i, raw->plane_size[i], raw->stride[i]);
+ MFC_WRITEL(raw->plane_size[i], MFC_REG_D_FIRST_PLANE_DPB_SIZE + (i * 4));
+ MFC_WRITEL(ctx->raw_buf.stride[i],
+ MFC_REG_D_FIRST_PLANE_DPB_STRIDE_SIZE + (i * 4));
+ if (ctx->is_10bit) {
+ MFC_WRITEL(raw->stride_2bits[i], MFC_REG_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE + (i * 4));
+ MFC_WRITEL(raw->plane_size_2bits[i], MFC_REG_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
+ mfc_debug(2, "[FRAME][10BIT] 2bits buf[%d] size: %d, stride: %d\n",
+ i, raw->plane_size_2bits[i], raw->stride_2bits[i]);
+ }
+ }
+
+ /* set codec buffers */
+ MFC_WRITEL(buf_addr, MFC_REG_D_SCRATCH_BUFFER_ADDR);
+ MFC_WRITEL(ctx->scratch_buf_size, MFC_REG_D_SCRATCH_BUFFER_SIZE);
+ buf_addr += ctx->scratch_buf_size;
+ buf_size -= ctx->scratch_buf_size;
+
+ if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx))
+ MFC_WRITEL(ctx->mv_size, MFC_REG_D_MV_BUFFER_SIZE);
+
+ if (IS_VP9_DEC(ctx)){
+ MFC_WRITEL(buf_addr, MFC_REG_D_STATIC_BUFFER_ADDR);
+ MFC_WRITEL(DEC_STATIC_BUFFER_SIZE, MFC_REG_D_STATIC_BUFFER_SIZE);
+ buf_addr += DEC_STATIC_BUFFER_SIZE;
+ buf_size -= DEC_STATIC_BUFFER_SIZE;
+ }
+
+ if (IS_MPEG4_DEC(ctx) && dec->loop_filter_mpeg4) {
+ mfc_debug(2, "Add DPB for loop filter of MPEG4\n");
+ for (i = 0; i < NUM_MPEG4_LF_BUF; i++) {
+ MFC_WRITEL(buf_addr, MFC_REG_D_POST_FILTER_LUMA_DPB0 + (4 * i));
+ buf_addr += ctx->loopfilter_luma_size;
+ buf_size -= ctx->loopfilter_luma_size;
+
+ MFC_WRITEL(buf_addr, MFC_REG_D_POST_FILTER_CHROMA_DPB0 + (4 * i));
+ buf_addr += ctx->loopfilter_chroma_size;
+ buf_size -= ctx->loopfilter_chroma_size;
+ }
+ reg |= ((dec->loop_filter_mpeg4 & MFC_REG_D_INIT_BUF_OPT_LF_CTRL_MASK)
+ << MFC_REG_D_INIT_BUF_OPT_LF_CTRL_SHIFT);
+ }
+
+ reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT);
+
+ if (CODEC_NOT_CODED(ctx)) {
+ reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT);
+ mfc_debug(2, "Notcoded frame copy mode start\n");
+ }
+ /* Enable 10bit Dithering */
+ if (ctx->is_10bit) {
+ reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_DITHERING_EN_SHIFT);
+ /* 64byte align, It is vaid only for VP9 */
+ reg |= (0x1 << MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
+ } else {
+ /* 16byte align, It is vaid only for VP9 */
+ reg &= ~(0x1 << MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
+ }
+
+ MFC_WRITEL(reg, MFC_REG_D_INIT_BUFFER_OPTIONS);
+
+ frame_size_mv = ctx->mv_size;
+ MFC_WRITEL(dec->mv_count, MFC_REG_D_NUM_MV);
+ if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx)) {
+ for (i = 0; i < dec->mv_count; i++) {
+ /* To test alignment */
+ align_gap = buf_addr;
+ buf_addr = ALIGN(buf_addr, 16);
+ align_gap = buf_addr - align_gap;
+ buf_size -= align_gap;
+
+ MFC_WRITEL(buf_addr, MFC_REG_D_MV_BUFFER0 + i * 4);
+ buf_addr += frame_size_mv;
+ buf_size -= frame_size_mv;
+ }
+ }
+
+ mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
+ if (buf_size < 0) {
+ mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/* Set encoding ref & codec buffer */
+int mfc_set_enc_codec_buffers(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_enc *enc = ctx->enc_priv;
+ dma_addr_t buf_addr;
+ int buf_size;
+ int i;
+
+ mfc_debug_enter();
+
+ buf_addr = ctx->codec_buf.daddr;
+ buf_size = ctx->codec_buf.size;
+
+ mfc_debug(2, "[MEMINFO] codec buf 0x%llx, size: %d\n", buf_addr, buf_size);
+ mfc_debug(2, "DPB COUNT: %d\n", ctx->dpb_count);
+
+ MFC_WRITEL(buf_addr, MFC_REG_E_SCRATCH_BUFFER_ADDR);
+ MFC_WRITEL(ctx->scratch_buf_size, MFC_REG_E_SCRATCH_BUFFER_SIZE);
+ buf_addr += ctx->scratch_buf_size;
+ buf_size -= ctx->scratch_buf_size;
+
+ /* start address of per buffer is aligned */
+ for (i = 0; i < ctx->dpb_count; i++) {
+ MFC_WRITEL(buf_addr, MFC_REG_E_LUMA_DPB + (4 * i));
+ buf_addr += enc->luma_dpb_size;
+ buf_size -= enc->luma_dpb_size;
+ }
+ for (i = 0; i < ctx->dpb_count; i++) {
+ MFC_WRITEL(buf_addr, MFC_REG_E_CHROMA_DPB + (4 * i));
+ buf_addr += enc->chroma_dpb_size;
+ buf_size -= enc->chroma_dpb_size;
+ }
+ for (i = 0; i < ctx->dpb_count; i++) {
+ MFC_WRITEL(buf_addr, MFC_REG_E_ME_BUFFER + (4 * i));
+ buf_addr += enc->me_buffer_size;
+ buf_size -= enc->me_buffer_size;
+ }
+
+ MFC_WRITEL(buf_addr, MFC_REG_E_TMV_BUFFER0);
+ buf_addr += enc->tmv_buffer_size >> 1;
+ MFC_WRITEL(buf_addr, MFC_REG_E_TMV_BUFFER1);
+ buf_addr += enc->tmv_buffer_size >> 1;
+ buf_size -= enc->tmv_buffer_size;
+
+ mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
+ if (buf_size < 0) {
+ mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
+ return -ENOMEM;
+ }
+
+ mfc_debug_leave();
+
+ return 0;
+}
+
+/* Set registers for decoding stream buffer */
+int mfc_set_dec_stream_buffer(struct mfc_ctx *ctx, struct mfc_buf *mfc_buf,
+ unsigned int start_num_byte, unsigned int strm_size)
+{
+ struct mfc_dev *dev;
+ struct mfc_dec *dec;
+ unsigned int cpb_buf_size;
+ dma_addr_t addr;
+ int index = -1;
+
+ mfc_debug_enter();
+ if (!ctx) {
+ mfc_err_dev("no mfc context to run\n");
+ return -EINVAL;
+ }
+ dev = ctx->dev;
+ if (!dev) {
+ mfc_err_dev("no mfc device to run\n");
+ return -EINVAL;
+ }
+ dec = ctx->dec_priv;
+ if (!dec) {
+ mfc_err_dev("no mfc decoder to run\n");
+ return -EINVAL;
+ }
+
+ cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN);
+
+ if (mfc_buf) {
+ index = mfc_buf->vb.vb2_buf.index;
+ addr = mfc_buf->addr[0][0];
+ if (strm_size > set_strm_size_max(cpb_buf_size)) {
+ mfc_info_ctx("Decrease strm_size because of %d align: %u -> %u\n",
+ STREAM_BUF_ALIGN, strm_size, set_strm_size_max(cpb_buf_size));
+ strm_size = set_strm_size_max(cpb_buf_size);
+ mfc_buf->vb.vb2_buf.planes[0].bytesused = strm_size;
+ }
+ } else {
+ addr = 0;
+ }
+
+ mfc_debug(2, "[BUFINFO] ctx[%d] set src index: %d, addr: 0x%08llx\n",
+ ctx->num, index, addr);
+ mfc_debug(2, "[STREAM] strm_size: %#lx(%d), buf_size: %u, offset: %u\n",
+ strm_size, strm_size, cpb_buf_size, start_num_byte);
+
+ if (strm_size == 0)
+ mfc_info_ctx("stream size is 0\n");
+
+ MFC_WRITEL(strm_size, MFC_REG_D_STREAM_DATA_SIZE);
+ MFC_WRITEL(addr, MFC_REG_D_CPB_BUFFER_ADDR);
+ MFC_WRITEL(cpb_buf_size, MFC_REG_D_CPB_BUFFER_SIZE);
+ MFC_WRITEL(start_num_byte, MFC_REG_D_CPB_BUFFER_OFFSET);
+
+ if (mfc_buf)
+ MFC_TRACE_CTX("Set src[%d] fd: %d, %#llx\n",
+ index, mfc_buf->vb.vb2_buf.planes[0].m.fd, addr);
+
+ mfc_debug_leave();
+ return 0;
+}
+
+void mfc_set_enc_frame_buffer(struct mfc_ctx *ctx,
+ struct mfc_buf *mfc_buf, int num_planes)
+{
+ struct mfc_dev *dev = ctx->dev;
+ dma_addr_t addr[3] = { 0, 0, 0 };
+ dma_addr_t addr_2bit[2] = { 0, 0 };
+ int index, i;
+
+ if (!mfc_buf) {
+ mfc_debug(3, "enc zero buffer set\n");
+ goto buffer_set;
+ }
+
+ index = mfc_buf->vb.vb2_buf.index;
+ if (mfc_buf->num_valid_bufs > 0) {
+ for (i = 0; i < num_planes; i++) {
+ addr[i] = mfc_buf->addr[mfc_buf->next_index][i];
+ mfc_debug(2, "[BUFCON][BUFINFO] ctx[%d] set src index:%d, batch[%d], addr[%d]: 0x%08llx\n",
+ ctx->num, index, mfc_buf->next_index, i, addr[i]);
+ }
+ mfc_buf->next_index++;
+ } else {
+ for (i = 0; i < num_planes; i++) {
+ addr[i] = mfc_buf->addr[0][i];
+ mfc_debug(2, "[BUFINFO] ctx[%d] set src index:%d, addr[%d]: 0x%08llx\n",
+ ctx->num, index, i, addr[i]);
+ }
+ }
+
+buffer_set:
+ for (i = 0; i < num_planes; i++)
+ MFC_WRITEL(addr[i], MFC_REG_E_SOURCE_FIRST_ADDR + (i * 4));
+
+ if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M_S10B ||
+ ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M_S10B) {
+ addr_2bit[0] = addr[0] + NV12N_10B_Y_8B_SIZE(ctx->img_width, ctx->img_height);
+ addr_2bit[1] = addr[1] + NV12N_10B_CBCR_8B_SIZE(ctx->img_width, ctx->img_height);
+
+ for (i = 0; i < num_planes; i++) {
+ MFC_WRITEL(addr_2bit[i], MFC_REG_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
+ mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
+ ctx->num, i, addr_2bit[i]);
+ }
+ } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV16M_S10B ||
+ ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV61M_S10B) {
+ addr_2bit[0] = addr[0] + NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
+ addr_2bit[1] = addr[1] + NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+
+ for (i = 0; i < num_planes; i++) {
+ MFC_WRITEL(addr_2bit[i], MFC_REG_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
+ mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
+ ctx->num, i, addr_2bit[i]);
+ }
+ }
+}
+
+/* Set registers for encoding stream buffer */
+int mfc_set_enc_stream_buffer(struct mfc_ctx *ctx,
+ struct mfc_buf *mfc_buf)
+{
+ struct mfc_dev *dev = ctx->dev;
+ dma_addr_t addr;
+ unsigned int size, offset, index;
+
+ index = mfc_buf->vb.vb2_buf.index;
+ addr = mfc_buf->addr[0][0];
+ offset = mfc_buf->vb.vb2_buf.planes[0].data_offset;
+ size = (unsigned int)vb2_plane_size(&mfc_buf->vb.vb2_buf, 0);
+ size = ALIGN(size, 512);
+
+ MFC_WRITEL(addr, MFC_REG_E_STREAM_BUFFER_ADDR); /* 16B align */
+ MFC_WRITEL(size, MFC_REG_E_STREAM_BUFFER_SIZE);
+ MFC_WRITEL(offset, MFC_REG_E_STREAM_BUFFER_OFFSET);
+
+ mfc_debug(2, "[BUFINFO] ctx[%d] set dst index: %d, addr: 0x%08llx\n",
+ ctx->num, index, addr);
+ mfc_debug(2, "[STREAM] buf_size: %u, offset: %d\n", size, offset);
+
+ return 0;
+}
+
+void mfc_get_enc_frame_buffer(struct mfc_ctx *ctx,
+ dma_addr_t addr[], int num_planes)
+{
+ struct mfc_dev *dev = ctx->dev;
+ unsigned long enc_recon_y_addr, enc_recon_c_addr;
+ int i, addr_offset;
+
+ addr_offset = MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR;
+
+ for (i = 0; i < num_planes; i++)
+ addr[i] = MFC_READL(addr_offset + (i * 4));
+
+ enc_recon_y_addr = MFC_READL(MFC_REG_E_RECON_LUMA_DPB_ADDR);
+ enc_recon_c_addr = MFC_READL(MFC_REG_E_RECON_CHROMA_DPB_ADDR);
+
+ mfc_debug(2, "[MEMINFO] recon y: 0x%08lx c: 0x%08lx\n",
+ enc_recon_y_addr, enc_recon_c_addr);
+}
+
+void mfc_set_enc_stride(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ int i;
+
+ for (i = 0; i < ctx->raw_buf.num_planes; i++) {
+ MFC_WRITEL(ctx->raw_buf.stride[i],
+ MFC_REG_E_SOURCE_FIRST_STRIDE + (i * 4));
+ mfc_debug(2, "[FRAME] enc src plane[%d] stride: %d\n",
+ i, ctx->raw_buf.stride[i]);
+ }
+}
+
+int mfc_set_dynamic_dpb(struct mfc_ctx *ctx, struct mfc_buf *dst_mb)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ struct mfc_raw_info *raw = &ctx->raw_buf;
+ int dst_index;
+ int i;
+
+ dst_index = dst_mb->vb.vb2_buf.index;
+ set_bit(dst_index, &dec->available_dpb);
+ dec->dynamic_set = 1 << dst_index;
+ mfc_debug(2, "[DPB] ADDING Flag after: 0x%lx\n", dec->available_dpb);
+
+ /* for debugging about black bar detection */
+ if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar) {
+ for (i = 0; i < raw->num_planes; i++) {
+ dec->frame_vaddr[i][dec->frame_cnt] = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, i);
+ dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[0][i];
+ dec->frame_size[i][dec->frame_cnt] = raw->plane_size[i];
+ dec->index[i][dec->frame_cnt] = dst_index;
+ dec->fd[i][dec->frame_cnt] = dst_mb->vb.vb2_buf.planes[0].m.fd;
+ }
+ dec->frame_cnt++;
+ if (dec->frame_cnt >= 30)
+ dec->frame_cnt = 0;
+ }
+
+ /* decoder dst buffer CFW PROT */
+ mfc_protect_dpb(ctx, dst_mb);
+
+ for (i = 0; i < raw->num_planes; i++) {
+ MFC_WRITEL(raw->plane_size[i],
+ MFC_REG_D_FIRST_PLANE_DPB_SIZE + i * 4);
+ MFC_WRITEL(dst_mb->addr[0][i],
+ MFC_REG_D_FIRST_PLANE_DPB0 + (i * 0x100 + dst_index * 4));
+ if (ctx->is_10bit)
+ MFC_WRITEL(raw->plane_size_2bits[i],
+ MFC_REG_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
+ mfc_debug(2, "[BUFINFO][DPB] ctx[%d] set dst index: %d, addr[%d]: 0x%08llx\n",
+ ctx->num, dst_index, i, dst_mb->addr[0][i]);
+ }
+
+ MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
+ dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0],
+ dec->available_dpb, dec->dynamic_used);
+
+ return 0;
+}
+
+void mfc_set_pixel_format(struct mfc_dev *dev, unsigned int format)
+{
+ unsigned int reg = 0;
+ unsigned int pix_val, mem_type_10bit = 0;
+
+ if (dev->pdata->P010_decoding)
+ mem_type_10bit = 1;
+
+ switch (format) {
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12N:
+ case V4L2_PIX_FMT_NV12MT_16X16:
+ case V4L2_PIX_FMT_NV16M:
+ pix_val = 0;
+ break;
+ case V4L2_PIX_FMT_NV21M:
+ case V4L2_PIX_FMT_NV61M:
+ pix_val = 1;
+ break;
+ case V4L2_PIX_FMT_YVU420M:
+ pix_val = 2;
+ break;
+ case V4L2_PIX_FMT_YUV420M:
+ case V4L2_PIX_FMT_YUV420N:
+ pix_val = 3;
+ break;
+ /* For 10bit direct set */
+ case V4L2_PIX_FMT_NV12N_10B:
+ case V4L2_PIX_FMT_NV12M_S10B:
+ case V4L2_PIX_FMT_NV16M_S10B:
+ mem_type_10bit = 0;
+ pix_val = 0;
+ break;
+ case V4L2_PIX_FMT_NV12M_P010:
+ case V4L2_PIX_FMT_NV16M_P210:
+ mem_type_10bit = 1;
+ pix_val = 0;
+ break;
+ case V4L2_PIX_FMT_NV21M_S10B:
+ case V4L2_PIX_FMT_NV61M_S10B:
+ mem_type_10bit = 0;
+ pix_val = 1;
+ break;
+ case V4L2_PIX_FMT_NV21M_P010:
+ case V4L2_PIX_FMT_NV61M_P210:
+ mem_type_10bit = 1;
+ pix_val = 1;
+ break;
+ default:
+ pix_val = 0;
+ break;
+ }
+ reg |= pix_val;
+ reg |= (mem_type_10bit << 4);
+ MFC_WRITEL(reg, MFC_REG_PIXEL_FORMAT);
+ mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit for 10bit: %d (reg: %#x)\n",
+ pix_val, mem_type_10bit, reg);
+}
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_reg_api.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_REG_API_H
+#define __MFC_REG_API_H __FILE__
+
+#include "mfc_common.h"
+
+#include "mfc_utils.h"
+
+#define MFC_READL(offset) readl(dev->regs_base + (offset))
+#define MFC_WRITEL(data, offset) writel((data), dev->regs_base + (offset))
+
+#define MFC_MMU0_READL(offset) readl(dev->sysmmu0_base + (offset))
+#define MFC_MMU1_READL(offset) readl(dev->sysmmu1_base + (offset))
+
+#define HWFC_WRITEL(data, offset) writel((data), dev->hwfc_base + (offset))
+
+#define MMCACHE_READL(offset) readl(dev->mmcache.base + (offset))
+#define MMCACHE_WRITEL(data, offset) writel((data), dev->mmcache.base + (offset))
+
+/* version */
+#define mfc_get_fimv_info() ((MFC_READL(MFC_REG_FW_VERSION) \
+ >> MFC_REG_FW_VER_INFO_SHFT) \
+ & MFC_REG_FW_VER_INFO_MASK)
+#define mfc_get_fw_ver_year() ((MFC_READL(MFC_REG_FW_VERSION) \
+ >> MFC_REG_FW_VER_YEAR_SHFT) \
+ & MFC_REG_FW_VER_YEAR_MASK)
+#define mfc_get_fw_ver_month() ((MFC_READL(MFC_REG_FW_VERSION) \
+ >> MFC_REG_FW_VER_MONTH_SHFT) \
+ & MFC_REG_FW_VER_MONTH_MASK)
+#define mfc_get_fw_ver_date() ((MFC_READL(MFC_REG_FW_VERSION) \
+ >> MFC_REG_FW_VER_DATE_SHFT) \
+ & MFC_REG_FW_VER_DATE_MASK)
+#define mfc_get_fw_ver_all() ((MFC_READL(MFC_REG_FW_VERSION) \
+ >> MFC_REG_FW_VER_ALL_SHFT) \
+ & MFC_REG_FW_VER_ALL_MASK)
+#define mfc_get_mfc_version() ((MFC_READL(MFC_REG_MFC_VERSION) \
+ >> MFC_REG_MFC_VER_SHFT) \
+ & MFC_REG_MFC_VER_MASK)
+
+
+/* decoding & display information */
+#define mfc_get_dec_status() (MFC_READL(MFC_REG_D_DECODED_STATUS) \
+ & MFC_REG_DEC_STATUS_DECODED_STATUS_MASK)
+#define mfc_get_disp_status() (MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
+ & MFC_REG_DISP_STATUS_DISPLAY_STATUS_MASK)
+#define mfc_get_res_change() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
+ >> MFC_REG_DISP_STATUS_RES_CHANGE_SHIFT) \
+ & MFC_REG_DISP_STATUS_RES_CHANGE_MASK)
+#define mfc_get_black_bar_detection() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
+ >> MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_SHIFT) \
+ & MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_MASK)
+#define mfc_get_dpb_change() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
+ >> MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_SHIFT) \
+ & MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_MASK)
+#define mfc_get_scratch_change() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
+ >> MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT) \
+ & MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK)
+#define mfc_get_disp_frame_type() (MFC_READL(MFC_REG_D_DISPLAY_FRAME_TYPE) \
+ & MFC_REG_DISPLAY_FRAME_MASK)
+#define mfc_get_dec_frame_type() (MFC_READL(MFC_REG_D_DECODED_FRAME_TYPE) \
+ & MFC_REG_DECODED_FRAME_MASK)
+#define mfc_get_interlace_type() ((MFC_READL(MFC_REG_D_DISPLAY_FRAME_TYPE) \
+ >> MFC_REG_DISPLAY_TEMP_INFO_SHIFT) \
+ & MFC_REG_DISPLAY_TEMP_INFO_MASK)
+#define mfc_is_interlace_picture() ((MFC_READL(MFC_REG_D_DISPLAY_STATUS) \
+ >> MFC_REG_DISP_STATUS_INTERLACE_SHIFT)\
+ & MFC_REG_DISP_STATUS_INTERLACE_MASK)
+#define mfc_is_mbaff_picture() ((MFC_READL(MFC_REG_D_H264_INFO) \
+ >> MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT)\
+ & MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_MASK)
+#define mfc_get_img_width() MFC_READL(MFC_REG_D_DISPLAY_FRAME_WIDTH)
+#define mfc_get_img_height() MFC_READL(MFC_REG_D_DISPLAY_FRAME_HEIGHT)
+#define mfc_get_disp_y_addr() MFC_READL(MFC_REG_D_DISPLAY_LUMA_ADDR)
+#define mfc_get_dec_y_addr() MFC_READL(MFC_REG_D_DECODED_LUMA_ADDR)
+
+
+/* kind of interrupt */
+#define mfc_get_int_err() MFC_READL(MFC_REG_ERROR_CODE)
+#define mfc_get_err(x) (((x) >> MFC_REG_ERR_STATUS_SHIFT) \
+ & MFC_REG_ERR_STATUS_MASK)
+#define mfc_get_warn(x) (((x) >> MFC_REG_WARN_STATUS_SHIFT) \
+ & MFC_REG_WARN_STATUS_MASK)
+
+
+/* additional information */
+#define mfc_get_consumed_stream() MFC_READL(MFC_REG_D_DECODED_NAL_SIZE)
+#define mfc_get_dpb_count() MFC_READL(MFC_REG_D_MIN_NUM_DPB)
+#define mfc_get_min_dpb_size(x) MFC_READL(MFC_REG_D_MIN_FIRST_PLANE_DPB_SIZE + (x * 4))
+#define mfc_get_scratch_size() MFC_READL(MFC_REG_D_MIN_SCRATCH_BUFFER_SIZE)
+#define mfc_get_mv_count() MFC_READL(MFC_REG_D_MIN_NUM_MV)
+#define mfc_get_inst_no() MFC_READL(MFC_REG_RET_INSTANCE_ID)
+#define mfc_get_enc_dpb_count() MFC_READL(MFC_REG_E_NUM_DPB)
+#define mfc_get_enc_scratch_size() MFC_READL(MFC_REG_E_MIN_SCRATCH_BUFFER_SIZE)
+#define mfc_get_enc_strm_size() MFC_READL(MFC_REG_E_STREAM_SIZE)
+#define mfc_get_enc_slice_type() MFC_READL(MFC_REG_E_SLICE_TYPE)
+#define mfc_get_enc_pic_count() MFC_READL(MFC_REG_E_PICTURE_COUNT)
+#define mfc_get_sei_avail() MFC_READL(MFC_REG_D_SEI_AVAIL)
+#define mfc_get_sei_content_light() MFC_READL(MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI)
+#define mfc_get_sei_mastering0() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0)
+#define mfc_get_sei_mastering1() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1)
+#define mfc_get_sei_mastering2() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2)
+#define mfc_get_sei_mastering3() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3)
+#define mfc_get_sei_mastering4() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4)
+#define mfc_get_sei_mastering5() MFC_READL(MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5)
+#define mfc_get_sei_avail_frame_pack() (MFC_READL(MFC_REG_D_SEI_AVAIL) \
+ & MFC_REG_D_SEI_AVAIL_FRAME_PACK_MASK)
+#define mfc_get_sei_avail_content_light() ((MFC_READL(MFC_REG_D_SEI_AVAIL) \
+ >> MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT) \
+ & MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_MASK)
+#define mfc_get_sei_avail_mastering_display() ((MFC_READL(MFC_REG_D_SEI_AVAIL) \
+ >> MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT) \
+ & MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK)
+#define mfc_get_video_signal_type() ((MFC_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
+ >> MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT) \
+ & MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_MASK)
+#define mfc_get_colour_description() ((MFC_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
+ >> MFC_REG_D_COLOUR_DESCRIPTION_FLAG_SHIFT) \
+ & MFC_REG_D_COLOUR_DESCRIPTION_FLAG_MASK)
+#define mfc_get_black_bar_pos_x() ((MFC_READL(MFC_REG_D_BLACK_BAR_START_POS) \
+ >> MFC_REG_D_BLACK_BAR_START_X_SHIFT) \
+ & MFC_REG_D_BLACK_BAR_START_X_MASK)
+#define mfc_get_black_bar_pos_y() ((MFC_READL(MFC_REG_D_BLACK_BAR_START_POS) \
+ >> MFC_REG_D_BLACK_BAR_START_Y_SHIFT) \
+ & MFC_REG_D_BLACK_BAR_START_Y_MASK)
+#define mfc_get_black_bar_image_w() ((MFC_READL(MFC_REG_D_BLACK_BAR_IMAGE_SIZE) \
+ >> MFC_REG_D_BLACK_BAR_IMAGE_W_SHIFT) \
+ & MFC_REG_D_BLACK_BAR_IMAGE_W_MASK)
+#define mfc_get_black_bar_image_h() ((MFC_READL(MFC_REG_D_BLACK_BAR_IMAGE_SIZE) \
+ >> MFC_REG_D_BLACK_BAR_IMAGE_H_SHIFT) \
+ & MFC_REG_D_BLACK_BAR_IMAGE_H_MASK)
+#define mfc_get_mvc_disp_view_id() (MFC_READL(MFC_REG_D_MVC_VIEW_ID) \
+ & MFC_REG_D_MVC_VIEW_ID_DISP_MASK)
+#define mfc_get_profile() (MFC_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
+ & MFC_REG_D_DECODED_PIC_PROFILE_MASK)
+#define mfc_get_luma_bit_depth_minus8() ((MFC_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
+ >> MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_SHIFT) \
+ & MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_MASK)
+#define mfc_get_chroma_bit_depth_minus8() ((MFC_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
+ >> MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT) \
+ & MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_MASK)
+#define mfc_get_dec_used_flag() MFC_READL(MFC_REG_D_USED_DPB_FLAG_LOWER)
+#define mfc_get_enc_nal_done_info() ((MFC_READL(MFC_REG_E_NAL_DONE_INFO) & (0x3 << 4)) >> 4)
+#define mfc_get_chroma_format() (MFC_READL(MFC_REG_D_CHROMA_FORMAT) \
+ & MFC_REG_D_CHROMA_FORMAT_MASK)
+#define mfc_get_color_range() ((MFC_READL(MFC_REG_D_CHROMA_FORMAT) \
+ >> MFC_REG_D_COLOR_RANGE_SHIFT) \
+ & MFC_REG_D_COLOR_RANGE_MASK)
+#define mfc_get_color_space() ((MFC_READL(MFC_REG_D_CHROMA_FORMAT) \
+ >> MFC_REG_D_COLOR_SPACE_SHIFT) \
+ & MFC_REG_D_COLOR_SPACE_MASK)
+#define mfc_get_num_of_tile() ((MFC_READL(MFC_REG_D_DECODED_STATUS) \
+ >> MFC_REG_DEC_STATUS_NUM_OF_TILE_SHIFT) \
+ & MFC_REG_DEC_STATUS_NUM_OF_TILE_MASK)
+
+
+/* nal queue information */
+#define mfc_get_nal_q_input_count() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_COUNT)
+#define mfc_get_nal_q_output_count() MFC_READL(MFC_REG_NAL_QUEUE_OUTPUT_COUNT)
+#define mfc_get_nal_q_input_exe_count() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT)
+#define mfc_get_nal_q_info() MFC_READL(MFC_REG_NAL_QUEUE_INFO)
+#define mfc_get_nal_q_input_addr() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_ADDR)
+#define mfc_get_nal_q_input_size() MFC_READL(MFC_REG_NAL_QUEUE_INPUT_SIZE)
+#define mfc_get_nal_q_output_addr() MFC_READL(MFC_REG_NAL_QUEUE_OUTPUT_ADDR)
+#define mfc_get_nal_q_output_ize() MFC_READL(MFC_REG_NAL_QUEUE_OUTPUT_SIZE)
+
+static inline void mfc_reset_nal_queue_registers(struct mfc_dev *dev)
+{
+ MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_INPUT_COUNT);
+ MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_OUTPUT_COUNT);
+ MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT);
+ MFC_WRITEL(0x0, MFC_REG_NAL_QUEUE_INFO);
+}
+
+static inline void mfc_update_nal_queue_input(struct mfc_dev *dev,
+ dma_addr_t addr, unsigned int size)
+{
+ MFC_WRITEL(addr, MFC_REG_NAL_QUEUE_INPUT_ADDR);
+ MFC_WRITEL(size, MFC_REG_NAL_QUEUE_INPUT_SIZE);
+}
+
+static inline void mfc_update_nal_queue_output(struct mfc_dev *dev,
+ dma_addr_t addr, unsigned int size)
+{
+ MFC_WRITEL(addr, MFC_REG_NAL_QUEUE_OUTPUT_ADDR);
+ MFC_WRITEL(size, MFC_REG_NAL_QUEUE_OUTPUT_SIZE);
+}
+
+static inline void mfc_update_nal_queue_input_count(struct mfc_dev *dev,
+ unsigned int input_count)
+{
+ MFC_WRITEL(input_count, MFC_REG_NAL_QUEUE_INPUT_COUNT);
+}
+
+static inline void mfc_dec_store_crop_info(struct mfc_ctx *ctx)
+{
+ struct mfc_dev *dev = ctx->dev;
+ struct mfc_dec *dec = ctx->dec_priv;
+ u32 left, right, top, bottom;
+
+ left = MFC_READL(MFC_REG_D_DISPLAY_CROP_INFO1);
+ right = left >> MFC_REG_D_SHARED_CROP_RIGHT_SHIFT;
+ left = left & MFC_REG_D_SHARED_CROP_LEFT_MASK;
+ top = MFC_READL(MFC_REG_D_DISPLAY_CROP_INFO2);
+ bottom = top >> MFC_REG_D_SHARED_CROP_BOTTOM_SHIFT;
+ top = top & MFC_REG_D_SHARED_CROP_TOP_MASK;
+
+ dec->cr_left = left;
+ dec->cr_right = right;
+ dec->cr_top = top;
+ dec->cr_bot = bottom;
+}
+
+static inline void mfc_clear_enc_res_change(struct mfc_dev *dev)
+{
+ unsigned int reg = 0;
+
+ reg = MFC_READL(MFC_REG_E_PARAM_CHANGE);
+ reg &= ~(0x7 << 6);
+ MFC_WRITEL(reg, MFC_REG_E_PARAM_CHANGE);
+}
+
+static inline void mfc_clear_roi_enable(struct mfc_dev *dev)
+{
+ unsigned int reg = 0;
+
+ reg = MFC_READL(MFC_REG_E_RC_ROI_CTRL);
+ reg &= ~(0x1);
+ MFC_WRITEL(reg, MFC_REG_E_RC_ROI_CTRL);
+}
+
+void mfc_dbg_enable(struct mfc_dev *dev);
+void mfc_dbg_disable(struct mfc_dev *dev);
+void mfc_dbg_set_addr(struct mfc_dev *dev);
+
+void mfc_otf_set_frame_addr(struct mfc_ctx *ctx, int num_planes);
+void mfc_otf_set_stream_size(struct mfc_ctx *ctx, unsigned int size);
+void mfc_otf_set_hwfc_index(struct mfc_ctx *ctx, int job_id);
+
+int mfc_set_dec_codec_buffers(struct mfc_ctx *ctx);
+int mfc_set_enc_codec_buffers(struct mfc_ctx *mfc_ctx);
+
+int mfc_set_dec_stream_buffer(struct mfc_ctx *ctx,
+ struct mfc_buf *mfc_buf,
+ unsigned int start_num_byte,
+ unsigned int buf_size);
+
+void mfc_set_enc_frame_buffer(struct mfc_ctx *ctx,
+ struct mfc_buf *mfc_buf, int num_planes);
+int mfc_set_enc_stream_buffer(struct mfc_ctx *ctx,
+ struct mfc_buf *mfc_buf);
+
+void mfc_get_enc_frame_buffer(struct mfc_ctx *ctx,
+ dma_addr_t addr[], int num_planes);
+void mfc_set_enc_stride(struct mfc_ctx *ctx);
+
+int mfc_set_dynamic_dpb(struct mfc_ctx *ctx, struct mfc_buf *dst_vb);
+
+void mfc_set_pixel_format(struct mfc_dev *dev, unsigned int format);
+
+#endif /* __MFC_REG_API_H */
--- /dev/null
+/*
+ * drivers/media/platform/exynos/mfc/mfc_regs.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_REGS_H
+#define __MFC_REGS_H __FILE__
+
+#define MFC_MMU_INTERRUPT_STATUS 0x0060
+#define MFC_MMU_FAULT_TRANS_INFO 0x0078
+#define MFC_MMU_FAULT_TRANS_INFO_RW_MASK 0x100000
+#define MFC_MMU_FAULT_TRANS_INFO_AXID_MASK 0xFFFF
+
+#define HWFC_ENCODING_IDX 0x4
+
+/* Codec Common Registers */
+#define MFC_REG_RISC_ON 0x0000
+#define MFC_REG_RISC2HOST_INT 0x003C
+#define MFC_REG_HOST2RISC_INT 0x0044
+#define MFC_REG_RISC_BASE_ADDRESS 0x0054
+
+#define MFC_REG_MFC_FW_CLOCK 0x1060
+#define MFC_REG_MFC_RESET 0x1070
+
+#define MFC_REG_HOST2RISC_CMD 0x1100
+#define MFC_REG_RISC2HOST_CMD 0x1104
+
+#define MFC_REG_MFC_BUS_STATUS 0x7018
+#define MFC_REG_MFC_RPEND 0x7028
+#define MFC_REG_MFC_WPEND 0x702C
+#define MFC_REG_MFC_BUS_RESET_CTRL 0x7110
+#define MFC_REG_MFC_OFF 0x7120
+#define MFC_REG_MFC_STATE 0x7124
+
+#define MFC_REG_FW_VERSION 0xF000
+#define MFC_REG_INSTANCE_ID 0xF008
+#define MFC_REG_CODEC_TYPE 0xF00C
+#define MFC_REG_CONTEXT_MEM_ADDR 0xF014
+#define MFC_REG_CONTEXT_MEM_SIZE 0xF018
+#define MFC_REG_SHARED_MEM_ADDR 0xF01C
+#define MFC_REG_PIXEL_FORMAT 0xF020
+
+#define MFC_REG_METADATA_ENABLE 0xF024
+#define MFC_REG_MFC_VERSION 0xF028
+#define MFC_REG_DBG_INFO_ENABLE 0xF02C
+#define MFC_REG_DBG_BUFFER_ADDR 0xF030
+#define MFC_REG_DBG_BUFFER_SIZE 0xF034
+
+#define MFC_REG_CODEC_CONTROL 0xF038
+#define MFC_REG_DEC_TIMEOUT_VALUE 0xF03C
+#define MFC_REG_HED_SHARED_MEM_ADDR 0xF040
+
+/* NAL QUEUE */
+#define MFC_REG_NAL_QUEUE_INPUT_ADDR 0xF044
+#define MFC_REG_NAL_QUEUE_INPUT_SIZE 0xF048
+#define MFC_REG_NAL_QUEUE_OUTPUT_ADDR 0xF04C
+#define MFC_REG_NAL_QUEUE_OUTPUT_SIZE 0xF050
+#define MFC_REG_NAL_QUEUE_INPUT_COUNT 0xF054
+
+#define MFC_REG_RET_INSTANCE_ID 0xF070
+#define MFC_REG_ERROR_CODE 0xF074
+#define MFC_REG_DBG_BUFFER_OUTPUT_SIZE 0xF078
+#define MFC_REG_METADATA_STATUS 0xF07C
+
+#define MFC_REG_DBG_INFO_STAGE_COUNTER 0xF088
+
+/* NAL QUEUE */
+#define MFC_REG_NAL_QUEUE_OUTPUT_COUNT 0xF08C
+#define MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT 0xF090
+#define MFC_REG_NAL_QUEUE_INFO 0xF094
+
+/* Decoder Registers */
+#define MFC_REG_D_CRC_CTRL 0xF0B0
+#define MFC_REG_D_DEC_OPTIONS 0xF0B4
+
+#define MFC_REG_D_DISPLAY_DELAY 0xF0B8
+
+#define MFC_REG_D_SET_FRAME_WIDTH 0xF0BC
+#define MFC_REG_D_SET_FRAME_HEIGHT 0xF0C0
+
+#define MFC_REG_D_SEI_ENABLE 0xF0C4
+
+#define MFC_REG_D_FORCE_PIXEL_VAL 0xF0C8
+
+/* Buffer setting registers */
+/* Session return */
+#define MFC_REG_D_MIN_NUM_DPB 0xF0F0
+#define MFC_REG_D_MIN_FIRST_PLANE_DPB_SIZE 0xF0F4
+#define MFC_REG_D_MIN_SECOND_PLANE_DPB_SIZE 0xF0F8
+#define MFC_REG_D_MIN_THIRD_PLANE_DPB_SIZE 0xF0FC
+#define MFC_REG_D_MIN_NUM_MV 0xF100
+#define MFC_REG_D_MVC_NUM_VIEWS 0xF104
+#define MFC_REG_D_MIN_SCRATCH_BUFFER_SIZE 0xF108
+#define MFC_REG_D_MIN_FIRST_PLANE_2BIT_DPB_SIZE 0xF10C
+#define MFC_REG_D_MIN_SECOND_PLANE_2BIT_DPB_SIZE 0xF110
+#define MFC_REG_D_POST_FILTER_LUMA_DPB0 0xF120
+#define MFC_REG_D_POST_FILTER_LUMA_DPB1 0xF124
+#define MFC_REG_D_POST_FILTER_CHROMA_DPB0 0xF128
+#define MFC_REG_D_POST_FILTER_CHROMA_DPB1 0xF12C
+
+/* Buffers */
+#define MFC_REG_D_NUM_DPB 0xF130
+#define MFC_REG_D_NUM_MV 0xF134
+#define MFC_REG_D_FIRST_PLANE_DPB_STRIDE_SIZE 0xF138
+#define MFC_REG_D_SECOND_PLANE_DPB_STRIDE_SIZE 0xF13C
+#define MFC_REG_D_THIRD_PLANE_DPB_STRIDE_SIZE 0xF140
+#define MFC_REG_D_FIRST_PLANE_DPB_SIZE 0xF144
+#define MFC_REG_D_SECOND_PLANE_DPB_SIZE 0xF148
+#define MFC_REG_D_THIRD_PLANE_DPB_SIZE 0xF14C
+#define MFC_REG_D_MV_BUFFER_SIZE 0xF150
+#define MFC_REG_D_INIT_BUFFER_OPTIONS 0xF154
+#define MFC_REG_D_FIRST_PLANE_DPB0 0xF160
+#define MFC_REG_D_SECOND_PLANE_DPB0 0xF260
+#define MFC_REG_D_THIRD_PLANE_DPB0 0xF360
+#define MFC_REG_D_MV_BUFFER0 0xF460
+#define MFC_REG_D_SCRATCH_BUFFER_ADDR 0xF560
+#define MFC_REG_D_SCRATCH_BUFFER_SIZE 0xF564
+#define MFC_REG_D_METADATA_BUFFER_ADDR 0xF568
+#define MFC_REG_D_METADATA_BUFFER_SIZE 0xF56C
+
+#define MFC_REG_D_STATIC_BUFFER_ADDR 0xF570
+#define MFC_REG_D_STATIC_BUFFER_SIZE 0xF574
+#define MFC_REG_D_FIRST_PLANE_2BIT_DPB_SIZE 0xF578
+#define MFC_REG_D_SECOND_PLANE_2BIT_DPB_SIZE 0xF57C
+#define MFC_REG_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE 0xF580
+#define MFC_REG_D_SECOND_PLANE_2BIT_DPB_STRIDE_SIZE 0xF584
+
+#define MFC_REG_D_NAL_START_OPTIONS 0xF5AC
+
+/* Nal cmd */
+#define MFC_REG_D_CPB_BUFFER_ADDR 0xF5B0
+#define MFC_REG_D_CPB_BUFFER_SIZE 0xF5B4
+#define MFC_REG_D_AVAILABLE_DPB_FLAG_UPPER 0xF5B8
+#define MFC_REG_D_AVAILABLE_DPB_FLAG_LOWER 0xF5BC
+#define MFC_REG_D_CPB_BUFFER_OFFSET 0xF5C0
+#define MFC_REG_D_SLICE_IF_ENABLE 0xF5C4
+#define MFC_REG_D_PICTURE_TAG 0xF5C8
+#define MFC_REG_D_STREAM_DATA_SIZE 0xF5D0
+#define MFC_REG_D_DYNAMIC_DPB_FLAG_UPPER 0xF5D4
+#define MFC_REG_D_DYNAMIC_DPB_FLAG_LOWER 0xF5D8
+
+/* Nal return */
+#define MFC_REG_D_DISPLAY_FRAME_WIDTH 0xF600
+#define MFC_REG_D_DISPLAY_FRAME_HEIGHT 0xF604
+#define MFC_REG_D_DISPLAY_STATUS 0xF608
+#define MFC_REG_D_DISPLAY_FIRST_PLANE_ADDR 0xF60C
+#define MFC_REG_D_DISPLAY_SECOND_PLANE_ADDR 0xF610
+#define MFC_REG_D_DISPLAY_THIRD_PLANE_ADDR 0xF614
+#define MFC_REG_D_DISPLAY_FRAME_TYPE 0xF618
+#define MFC_REG_D_DISPLAY_CROP_INFO1 0xF61C
+#define MFC_REG_D_DISPLAY_CROP_INFO2 0xF620
+#define MFC_REG_D_DISPLAY_PICTURE_PROFILE 0xF624
+#define MFC_REG_D_DISPLAY_FIRST_PLANE_CRC 0xF628
+#define MFC_REG_D_DISPLAY_SECOND_PLANE_CRC 0xF62C
+#define MFC_REG_D_DISPLAY_THIRD_PLANE_CRC 0xF630
+#define MFC_REG_D_DISPLAY_ASPECT_RATIO 0xF634
+#define MFC_REG_D_DISPLAY_EXTENDED_AR 0xF638
+#define MFC_REG_D_DECODED_FRAME_WIDTH 0xF63C
+#define MFC_REG_D_DECODED_FRAME_HEIGHT 0xF640
+#define MFC_REG_D_DECODED_STATUS 0xF644
+#define MFC_REG_D_DECODED_FIRST_PLANE_ADDR 0xF648
+#define MFC_REG_D_DECODED_SECOND_PLANE_ADDR 0xF64C
+#define MFC_REG_D_DECODED_THIRD_PLANE_ADDR 0xF650
+#define MFC_REG_D_DECODED_FRAME_TYPE 0xF654
+#define MFC_REG_D_DECODED_CROP_INFO1 0xF658
+#define MFC_REG_D_DECODED_CROP_INFO2 0xF65C
+#define MFC_REG_D_DECODED_PICTURE_PROFILE 0xF660
+#define MFC_REG_D_DECODED_NAL_SIZE 0xF664
+#define MFC_REG_D_DECODED_FIRST_PLANE_CRC 0xF668
+#define MFC_REG_D_DECODED_SECOND_PLANE_CRC 0xF66C
+#define MFC_REG_D_DECODED_THIRD_PLANE_CRC 0xF670
+#define MFC_REG_D_RET_PICTURE_TAG_TOP 0xF674
+#define MFC_REG_D_RET_PICTURE_TAG_BOT 0xF678
+#define MFC_REG_D_RET_PICTURE_TIME_TOP 0xF67C
+#define MFC_REG_D_RET_PICTURE_TIME_BOT 0xF680
+#define MFC_REG_D_CHROMA_FORMAT 0xF684
+
+#define MFC_REG_D_VC1_INFO 0xF688
+#define MFC_REG_D_MPEG4_INFO 0xF68C
+#define MFC_REG_D_H264_INFO 0xF690
+#define MFC_REG_D_HEVC_INFO 0xF6A0
+#define MFC_REG_D_BPG_INFO 0xF6A8
+
+#define MFC_REG_D_METADATA_ADDR_CONCEALED_MB 0xF6B0
+#define MFC_REG_D_METADATA_SIZE_CONCEALED_MB 0xF6B4
+#define MFC_REG_D_METADATA_ADDR_VC1_PARAM 0xF6B8
+#define MFC_REG_D_METADATA_SIZE_VC1_PARAM 0xF6BC
+#define MFC_REG_D_METADATA_ADDR_SEI_NAL 0xF6C0
+#define MFC_REG_D_METADATA_SIZE_SEI_NAL 0xF6C4
+#define MFC_REG_D_METADATA_ADDR_VUI 0xF6C8
+#define MFC_REG_D_METADATA_SIZE_VUI 0xF6CC
+#define MFC_REG_D_METADATA_ADDR_MVCVUI 0xF6D0
+#define MFC_REG_D_METADATA_SIZE_MVCVUI 0xF6D4
+
+#define MFC_REG_D_MVC_VIEW_ID 0xF6D8
+
+#define MFC_REG_D_SEI_AVAIL 0xF6DC
+#define MFC_REG_D_FRAME_PACK_ARRGMENT_ID 0xF6E0
+#define MFC_REG_D_FRAME_PACK_SEI_INFO 0xF6E4
+#define MFC_REG_D_FRAME_PACK_GRID_POS 0xF6E8
+
+#define MFC_REG_D_DISPLAY_RECOVERY_SEI_INFO 0xF6EC
+#define MFC_REG_D_DECODED_RECOVERY_SEI_INFO 0xF6F0
+
+#define MFC_REG_D_DISPLAY_FIRST_PLANE_2BIT_CRC 0xF6FC
+#define MFC_REG_D_DISPLAY_SECOND_PLANE_2BIT_CRC 0xF700
+#define MFC_REG_D_DECODED_FIRST_PLANE_2BIT_CRC 0xF704
+#define MFC_REG_D_DECODED_SECOND_PLANE_2BIT_CRC 0xF708
+
+#define MFC_REG_D_VIDEO_SIGNAL_TYPE 0xF70C
+#define MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI 0xF710
+#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0 0xF714
+#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1 0xF718
+
+#define MFC_REG_D_USED_DPB_FLAG_UPPER 0xF720
+#define MFC_REG_D_USED_DPB_FLAG_LOWER 0xF724
+
+#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2 0xF728
+#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3 0xF72C
+#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4 0xF730
+#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5 0xF734
+
+#define MFC_REG_D_BLACK_BAR_START_POS 0xF738
+#define MFC_REG_D_BLACK_BAR_IMAGE_SIZE 0xF73C
+
+#define MFC_REG_D_DISPLAY_LUMA_ADDR 0xF60C
+#define MFC_REG_D_DISPLAY_CHROMA_ADDR 0xF610
+
+#define MFC_REG_D_DECODED_LUMA_ADDR 0xF648
+#define MFC_REG_D_DECODED_CHROMA_ADDR 0xF64C
+
+/* Encoder Registers */
+#define MFC_REG_E_CROPPED_FRAME_WIDTH 0xF778
+#define MFC_REG_E_CROPPED_FRAME_HEIGHT 0xF77C
+#define MFC_REG_E_FRAME_CROP_OFFSET 0xF780
+#define MFC_REG_E_ENC_OPTIONS 0xF784
+#define MFC_REG_E_PICTURE_PROFILE 0xF788
+#define MFC_REG_E_VBV_BUFFER_SIZE 0xF78C
+#define MFC_REG_E_VBV_INIT_DELAY 0xF790
+#define MFC_REG_E_FIXED_PICTURE_QP 0xF794
+#define MFC_REG_E_RC_CONFIG 0xF798
+#define MFC_REG_E_RC_QP_BOUND 0xF79C
+#define MFC_REG_E_RC_QP_BOUND_PB 0xF7A0
+#define MFC_REG_E_RC_MODE 0xF7A4
+
+#define MFC_REG_E_MB_RC_CONFIG 0xF7A8
+#define MFC_REG_E_PADDING_CTRL 0xF7AC
+#define MFC_REG_E_AIR_THRESHOLD 0xF7B0
+
+#define MFC_REG_E_MV_HOR_RANGE 0xF7B4
+#define MFC_REG_E_MV_VER_RANGE 0xF7B8
+
+#define MFC_REG_E_HIGH_QUALITY_MODE 0xF7C0
+#define MFC_REG_E_VIDEO_SIGNAL_TYPE 0xF7C4
+
+#define MFC_REG_E_SAO_WEIGHT0 0xF7C8
+#define MFC_REG_E_SAO_WEIGHT1 0xF7CC
+
+#define MFC_REG_E_NUM_DPB 0xF890
+#define MFC_REG_E_MIN_SCRATCH_BUFFER_SIZE 0xF894
+
+#define MFC_REG_E_LUMA_DPB 0xF8C0
+#define MFC_REG_E_CHROMA_DPB 0xF904
+#define MFC_REG_E_ME_BUFFER 0xF948
+
+#define MFC_REG_E_SCRATCH_BUFFER_ADDR 0xF98C
+#define MFC_REG_E_SCRATCH_BUFFER_SIZE 0xF990
+#define MFC_REG_E_TMV_BUFFER0 0xF994
+#define MFC_REG_E_TMV_BUFFER1 0xF998
+#define MFC_REG_E_IR_BUFFER_ADDR 0xF99C
+#define MFC_REG_E_SOURCE_FIRST_2BIT_ADDR 0xF9D0
+#define MFC_REG_E_SOURCE_SECOND_2BIT_ADDR 0xF9D4
+#define MFC_REG_E_SOURCE_FIRST_2BIT_STRIDE 0xF9D8
+#define MFC_REG_E_SOURCE_SECOND_2BIT_STRIDE 0xF9DC
+#define MFC_REG_E_SOURCE_FIRST_ADDR 0xF9E0
+#define MFC_REG_E_SOURCE_SECOND_ADDR 0xF9E4
+#define MFC_REG_E_SOURCE_THIRD_ADDR 0xF9E8
+#define MFC_REG_E_SOURCE_FIRST_STRIDE 0xF9EC
+#define MFC_REG_E_SOURCE_SECOND_STRIDE 0xF9F0
+#define MFC_REG_E_SOURCE_THIRD_STRIDE 0xF9F4
+#define MFC_REG_E_STREAM_BUFFER_ADDR 0xF9F8
+#define MFC_REG_E_STREAM_BUFFER_SIZE 0xF9FC
+#define MFC_REG_E_ROI_BUFFER_ADDR 0xFA00
+
+#define MFC_REG_E_PARAM_CHANGE 0xFA04
+#define MFC_REG_E_IR_SIZE 0xFA08
+#define MFC_REG_E_GOP_CONFIG 0xFA0C
+#define MFC_REG_E_MSLICE_MODE 0xFA10
+#define MFC_REG_E_MSLICE_SIZE_MB 0xFA14
+#define MFC_REG_E_MSLICE_SIZE_BITS 0xFA18
+#define MFC_REG_E_FRAME_INSERTION 0xFA1C
+
+#define MFC_REG_E_RC_FRAME_RATE 0xFA20
+#define MFC_REG_E_RC_BIT_RATE 0xFA24
+#define MFC_REG_E_RC_ROI_CTRL 0xFA2C
+#define MFC_REG_E_PICTURE_TAG 0xFA30
+#define MFC_REG_E_BIT_COUNT_ENABLE 0xFA34
+#define MFC_REG_E_MAX_BIT_COUNT 0xFA38
+#define MFC_REG_E_MIN_BIT_COUNT 0xFA3C
+
+#define MFC_REG_E_METADATA_BUFFER_ADDR 0xFA40
+#define MFC_REG_E_METADATA_BUFFER_SIZE 0xFA44
+
+#define MFC_REG_E_ENCODING_ORDER_TIME_INFO 0xFA50
+#define MFC_REG_E_ENCODING_ORDER_INFO 0xFA54
+#define MFC_REG_E_STREAM_BUFFER_OFFSET 0xFA58
+#define MFC_REG_E_GOP_CONFIG2 0xFA5C
+#define MFC_REG_E_WEIGHT_FOR_WEIGHTED_PREDICTION 0xFA60
+
+#define MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR 0xFA70
+#define MFC_REG_E_ENCODED_SOURCE_SECOND_ADDR 0xFA74
+#define MFC_REG_E_ENCODED_SOURCE_THIRD_ADDR 0xFA78
+
+#define MFC_REG_E_STREAM_SIZE 0xFA80
+#define MFC_REG_E_SLICE_TYPE 0xFA84
+#define MFC_REG_E_PICTURE_COUNT 0xFA88
+#define MFC_REG_E_RET_PICTURE_TAG 0xFA8C
+
+#define MFC_REG_E_RECON_LUMA_DPB_ADDR 0xFA9C
+#define MFC_REG_E_RECON_CHROMA_DPB_ADDR 0xFAA0
+#define MFC_REG_E_METADATA_ADDR_ENC_SLICE 0xFAA4
+#define MFC_REG_E_METADATA_SIZE_ENC_SLICE 0xFAA8
+
+#define MFC_REG_E_NAL_DONE_INFO 0xFAEC
+
+#define MFC_REG_E_MPEG4_OPTIONS 0xFB10
+#define MFC_REG_E_MPEG4_HEC_PERIOD 0xFB14
+
+#define MFC_REG_E_BPG_OPTIONS 0xFB1C
+#define MFC_REG_E_BPG_EXT_CTB_QP_CTRL 0xFB20
+#define MFC_REG_E_BPG_CHROMA_QP_OFFSET 0xFB24
+#define MFC_REG_E_BPG_EXTENSION_DATA_SIZE 0xFB28
+
+#define MFC_REG_E_H264_HD_SVC_EXTENSION_0 0xFB44
+#define MFC_REG_E_H264_HD_SVC_EXTENSION_1 0xFB48
+#define MFC_REG_E_ASPECT_RATIO 0xFB4C
+#define MFC_REG_E_EXTENDED_SAR 0xFB50
+
+#define MFC_REG_E_H264_OPTIONS 0xFB54
+#define MFC_REG_E_H264_OPTIONS_2 0xFB58
+#define MFC_REG_E_H264_LF_ALPHA_OFFSET 0xFB5C
+#define MFC_REG_E_H264_LF_BETA_OFFSET 0xFB60
+#define MFC_REG_E_H264_REFRESH_PERIOD 0xFB64
+
+#define MFC_REG_E_H264_FMO_SLICE_GRP_MAP_TYPE 0xFB68
+#define MFC_REG_E_H264_FMO_NUM_SLICE_GRP_MINUS1 0xFB6C
+#define MFC_REG_E_H264_FMO_SLICE_GRP_CHANGE_DIR 0xFB70
+#define MFC_REG_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1 0xFB74
+#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_0 0xFB78
+#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_1 0xFB7C
+#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_2 0xFB80
+#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_3 0xFB84
+
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_0 0xFB88
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_1 0xFB8C
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_2 0xFB90
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_3 0xFB94
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_4 0xFB98
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_5 0xFB9C
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_6 0xFBA0
+#define MFC_REG_E_H264_ASO_SLICE_ORDER_7 0xFBA4
+#define MFC_REG_E_H264_CHROMA_QP_OFFSET 0xFBA8
+
+#define MFC_REG_E_NUM_T_LAYER 0xFBAC
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER0 0xFBB0
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER1 0xFBB4
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER2 0xFBB8
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER3 0xFBBC
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER4 0xFBC0
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER5 0xFBC4
+#define MFC_REG_E_HIERARCHICAL_QP_LAYER6 0xFBC8
+
+/* For backward compatibility */
+#define MFC_REG_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
+
+#define MFC_REG_E_H264_NAL_CONTROL 0xFD14
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0 0xFD18
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER1 0xFD1C
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER2 0xFD20
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER3 0xFD24
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER4 0xFD28
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER5 0xFD2C
+#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER6 0xFD30
+
+#define MFC_REG_E_MVC_FRAME_QP_VIEW1 0xFD40
+#define MFC_REG_E_MVC_RC_FRAME_RATE_VIEW1 0xFD44
+#define MFC_REG_E_MVC_RC_BIT_RATE_VIEW1 0xFD48
+#define MFC_REG_E_MVC_RC_QBOUND_VIEW1 0xFD4C
+#define MFC_REG_E_MVC_RC_MODE_VIEW1 0xFD50
+#define MFC_REG_E_MVC_INTER_VIEW_PREDICTION_ON 0xFD80
+
+#define MFC_REG_E_VP9_OPTION 0xFD90
+#define MFC_REG_E_VP9_FILTER_OPTION 0xFD94
+#define MFC_REG_E_VP9_GOLDEN_FRAME_OPTION 0xFD98
+#define MFC_REG_E_VP8_OPTION 0xFDB0
+#define MFC_REG_E_VP8_FILTER_OPTION 0xFDB4
+#define MFC_REG_E_VP8_GOLDEN_FRAME_OPTION 0xFDB8
+
+#define MFC_REG_E_HEVC_OPTIONS_2 0xFDC4
+
+#define MFC_REG_E_HEVC_OPTIONS 0xFDD4
+#define MFC_REG_E_HEVC_REFRESH_PERIOD 0xFDD8
+#define MFC_REG_E_HEVC_CHROMA_QP_OFFSET 0xFDDC
+#define MFC_REG_E_HEVC_LF_BETA_OFFSET_DIV2 0xFDE0
+#define MFC_REG_E_HEVC_LF_TC_OFFSET_DIV2 0xFDE4
+#define MFC_REG_E_HEVC_NAL_CONTROL 0xFDE8
+
+#define MFC_REG_E_VP8_NAL_CONTROL 0xFDF0
+#define MFC_REG_E_VP9_NAL_CONTROL 0xFDF4
+#define MFC_REG_E_CONTENT_LIGHT_LEVEL_INFO_SEI 0xFDF8
+#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0 0xFDFC
+#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1 0xFE00
+#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2 0xFE04
+#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3 0xFE08
+#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4 0xFE0C
+#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5 0xFE10
+
+
+#define MFC_REG_REG_CLEAR_BEGIN 0xf000
+#define MFC_REG_REG_CLEAR_COUNT 1024
+
+
+/* Bit Definitions */
+/* 0x1100: MFC_REG_HOST2RISC_CMD */
+#define MFC_REG_H2R_CMD_EMPTY 0
+#define MFC_REG_H2R_CMD_SYS_INIT 1
+#define MFC_REG_H2R_CMD_OPEN_INSTANCE 2
+#define MFC_REG_H2R_CMD_SEQ_HEADER 3
+#define MFC_REG_H2R_CMD_INIT_BUFFERS 4
+#define MFC_REG_H2R_CMD_NAL_START 5
+#define MFC_REG_H2R_CMD_CLOSE_INSTANCE 6
+#define MFC_REG_H2R_CMD_SLEEP 7
+#define MFC_REG_H2R_CMD_WAKEUP 8
+#define MFC_REG_H2R_CMD_LAST_FRAME 9
+#define MFC_REG_H2R_CMD_DPB_FLUSH 10
+#define MFC_REG_H2R_CMD_NAL_ABORT 11
+#define MFC_REG_H2R_CMD_CACHE_FLUSH 12
+#define MFC_REG_H2R_CMD_NAL_QUEUE 13
+#define MFC_REG_H2R_CMD_STOP_QUEUE 14
+
+
+/* 0x1104: MFC_REG_RISC2HOST_CMD */
+#define MFC_REG_RISC2HOST_CMD_MASK 0x1FFFF
+#define MFC_REG_R2H_CMD_EMPTY 0
+#define MFC_REG_R2H_CMD_SYS_INIT_RET 1
+#define MFC_REG_R2H_CMD_OPEN_INSTANCE_RET 2
+#define MFC_REG_R2H_CMD_SEQ_DONE_RET 3
+#define MFC_REG_R2H_CMD_INIT_BUFFERS_RET 4
+#define MFC_REG_R2H_CMD_CLOSE_INSTANCE_RET 6
+#define MFC_REG_R2H_CMD_SLEEP_RET 7
+#define MFC_REG_R2H_CMD_WAKEUP_RET 8
+#define MFC_REG_R2H_CMD_COMPLETE_SEQ_RET 9
+#define MFC_REG_R2H_CMD_DPB_FLUSH_RET 10
+#define MFC_REG_R2H_CMD_NAL_ABORT_RET 11
+#define MFC_REG_R2H_CMD_FW_STATUS_RET 12
+#define MFC_REG_R2H_CMD_FRAME_DONE_RET 13
+#define MFC_REG_R2H_CMD_FIELD_DONE_RET 14
+#define MFC_REG_R2H_CMD_SLICE_DONE_RET 15
+#define MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET 16
+#define MFC_REG_R2H_CMD_QUEUE_DONE_RET 17
+#define MFC_REG_R2H_CMD_COMPLETE_QUEUE_RET 18
+#define MFC_REG_R2H_CMD_CACHE_FLUSH_RET 20
+#define MFC_REG_R2H_CMD_ERR_RET 32
+
+
+/* 0xF000: MFC_REG_FW_VERSION */
+#define MFC_REG_FW_VER_INFO_MASK 0xFF
+#define MFC_REG_FW_VER_INFO_SHFT 24
+#define MFC_REG_FW_VER_YEAR_MASK 0xFF
+#define MFC_REG_FW_VER_YEAR_SHFT 16
+#define MFC_REG_FW_VER_MONTH_MASK 0xFF
+#define MFC_REG_FW_VER_MONTH_SHFT 8
+#define MFC_REG_FW_VER_DATE_MASK 0xFF
+#define MFC_REG_FW_VER_DATE_SHFT 0
+#define MFC_REG_FW_VER_ALL_MASK 0xFFFFFF
+#define MFC_REG_FW_VER_ALL_SHFT 0
+
+
+/* 0xF00C: MFC_REG_CODEC_TYPE */
+#define MFC_FORMATS_NO_CODEC -1
+/* Decoder */
+#define MFC_REG_CODEC_H264_DEC 0
+#define MFC_REG_CODEC_H264_MVC_DEC 1
+#define MFC_REG_CODEC_MPEG4_DEC 3
+#define MFC_REG_CODEC_FIMV1_DEC 4
+#define MFC_REG_CODEC_FIMV2_DEC 5
+#define MFC_REG_CODEC_FIMV3_DEC 6
+#define MFC_REG_CODEC_FIMV4_DEC 7
+#define MFC_REG_CODEC_H263_DEC 8
+#define MFC_REG_CODEC_VC1_RCV_DEC 9
+#define MFC_REG_CODEC_VC1_DEC 10
+#define MFC_REG_CODEC_MPEG2_DEC 13
+#define MFC_REG_CODEC_VP8_DEC 14
+#define MFC_REG_CODEC_HEVC_DEC 17
+#define MFC_REG_CODEC_VP9_DEC 18
+/* Encoder */
+#define MFC_REG_CODEC_H264_ENC 20
+#define MFC_REG_CODEC_H264_MVC_ENC 21
+#define MFC_REG_CODEC_MPEG4_ENC 23
+#define MFC_REG_CODEC_H263_ENC 24
+#define MFC_REG_CODEC_VP8_ENC 25
+#define MFC_REG_CODEC_HEVC_ENC 26
+#define MFC_REG_CODEC_VP9_ENC 27
+
+#define MFC_REG_CODEC_BPG_DEC 32
+#define MFC_REG_CODEC_BPG_ENC 33
+
+/* 0xF028: MFC_REG_MFC_VERSION */
+#define MFC_REG_MFC_VER_MASK 0xFFFFFFFF
+#define MFC_REG_MFC_VER_SHFT 0
+
+
+/* 0xF074: MFC_REG_ERROR_CODE */
+#define MFC_REG_ERR_STATUS_MASK 0xFFFF
+#define MFC_REG_ERR_STATUS_SHIFT 0
+#define MFC_REG_WARN_STATUS_MASK 0xFFFF
+#define MFC_REG_WARN_STATUS_SHIFT 16
+/* Error number */
+#define MFC_REG_ERR_BUFFER_FULL 18
+#define MFC_REG_ERR_NO_AVAILABLE_DPB 33
+#define MFC_REG_ERR_NO_KEY_FRAME 34
+#define MFC_REG_ERR_VPS_ONLY_ERROR 42
+#define MFC_REG_ERR_INSUFFICIENT_DPB_SIZE 57
+#define MFC_REG_ERR_INSUFFICIENT_NUM_DPB 58
+#define MFC_REG_ERR_INSUFFICIENT_MV_BUF_SIZE 60
+#define MFC_REG_ERR_NULL_SCRATCH 61
+#define MFC_REG_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE 62
+
+#define MFC_REG_ERR_UNSUPPORTED_FEATURE 100
+#define MFC_REG_ERR_UNSUPPORTED_RESOLUTION 101
+#define MFC_REG_ERR_HEADER_NOT_FOUND 102
+#define MFC_REG_ERR_INVAILD_NAL_TYPE 103
+#define MFC_REG_ERR_SEQUENCE_HEADER 104
+#define MFC_REG_ERR_MFC_TIMEOUT 140
+#define MFC_REG_ERR_TS_MUX_TIMEOUT 141
+#define MFC_REG_ERR_G2D_TIMEOUT 142
+#define MFC_REG_ERR_FRAME_CONCEAL 150
+#define MFC_REG_ERR_WARNINGS_START 160
+#define MFC_REG_ERR_BROKEN_LINK 161
+#define MFC_REG_ERR_SYNC_POINT_NOT_RECEIVED 190
+#define MFC_REG_ERR_NON_PAIRED_FIELD 191
+#define MFC_REG_ERR_WARNINGS_END 222
+
+
+/* 0xF0B4: MFC_REG_D_DEC_OPTIONS */
+#define MFC_REG_D_DEC_OPT_DISPLAY_DELAY_EN_SHIFT 3
+#define MFC_REG_D_DEC_OPT_FMO_ASO_CTRL_MASK 0x1
+#define MFC_REG_D_DEC_OPT_FMO_ASO_CTRL_SHIFT 4
+#define MFC_REG_D_DEC_OPT_IDR_DECODING_MASK 0x1
+#define MFC_REG_D_DEC_OPT_IDR_DECODING_SHIFT 6
+#define MFC_REG_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT 7
+#define MFC_REG_D_DEC_OPT_CONCEAL_CONTROL_SHIFT 8
+#define MFC_REG_D_DEC_OPT_PARALLEL_DISABLE_SHIFT 11
+#define MFC_REG_D_DEC_OPT_REALLOC_CONTROL_SHIFT 13
+#define MFC_REG_D_DEC_OPT_SPECIAL_PARSING_SHIFT 15
+#define MFC_REG_D_DEC_OPT_THUMBNAIL_DECODING 16
+
+
+/* 0xF0C4: MFC_REG_D_SEI_ENABLE */
+#define MFC_REG_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT 1
+#define MFC_REG_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT 2
+#define MFC_REG_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT 4
+#define MFC_REG_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT 5
+
+
+/* 0xF154: MFC_REG_D_INIT_BUFFER_OPTIONS */
+#define MFC_REG_D_INIT_BUF_OPT_LF_CTRL_MASK 0x3
+#define MFC_REG_D_INIT_BUF_OPT_LF_CTRL_SHIFT 1
+#define MFC_REG_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT 3
+#define MFC_REG_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT 4
+#define MFC_REG_D_INIT_BUF_OPT_DITHERING_EN_SHIFT 6
+#define MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN 7
+
+
+/* 0xF5AC: MFC_REG_D_NAL_START_OPTIONS */
+#define MFC_REG_D_NAL_START_OPT_BLACK_BAR_SHIFT 3
+
+
+/* 0xF608: MFC_REG_D_DISPLAY_STATUS */
+#define MFC_REG_DISP_STATUS_DISPLAY_STATUS_MASK 0x7
+#define MFC_REG_DISP_STATUS_INTERLACE_MASK 0x1
+#define MFC_REG_DISP_STATUS_INTERLACE_SHIFT 3
+#define MFC_REG_DISP_STATUS_RES_CHANGE_MASK 0x3
+#define MFC_REG_DISP_STATUS_RES_CHANGE_SHIFT 4
+#define MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_MASK 0x1
+#define MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_SHIFT 9
+#define MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK 0x1
+#define MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT 10
+#define MFC_REG_DISP_STATUS_NEED_EMPTY_DPB_MASK 0x1
+#define MFC_REG_DISP_STATUS_NEED_EMPTY_DPB_SHIFT 12
+#define MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_MASK 0x3
+#define MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_SHIFT 13
+#define MFC_REG_DISP_STATUS_NOT_DETECTED 0x0
+#define MFC_REG_DISP_STATUS_BLACK_BAR 0x1
+#define MFC_REG_DISP_STATUS_BLACK_SCREEN 0x2
+
+
+/* 0xF618: MFC_REG_D_DISPLAY_FRAME_TYPE */
+#define MFC_REG_DISPLAY_FRAME_MASK 0x7
+#define MFC_REG_DISPLAY_TEMP_INFO_MASK 0x1
+#define MFC_REG_DISPLAY_TEMP_INFO_SHIFT 7
+#define MFC_REG_DISPLAY_FRAME_NOT_CODED 0
+#define MFC_REG_DISPLAY_FRAME_I 1
+#define MFC_REG_DISPLAY_FRAME_P 2
+#define MFC_REG_DISPLAY_FRAME_B 3
+
+
+/* 0xF61C: MFC_REG_D_DISPLAY_CROP_INFO1 */
+#define MFC_REG_D_SHARED_CROP_LEFT_MASK 0xFFFF
+#define MFC_REG_D_SHARED_CROP_RIGHT_SHIFT 16
+
+
+/* 0xF620: MFC_REG_D_DISPLAY_CROP_INFO2 */
+#define MFC_REG_D_SHARED_CROP_TOP_MASK 0xFFFF
+#define MFC_REG_D_SHARED_CROP_BOTTOM_SHIFT 16
+
+
+/* 0xF644: MFC_REG_D_DECODED_STATUS */
+#define MFC_REG_DEC_STATUS_DECODED_STATUS_MASK 0x7
+#define MFC_REG_DEC_STATUS_DECODING_ONLY 0
+#define MFC_REG_DEC_STATUS_DECODING_DISPLAY 1
+#define MFC_REG_DEC_STATUS_DISPLAY_ONLY 2
+#define MFC_REG_DEC_STATUS_DECODING_EMPTY 3
+#define MFC_REG_DEC_STATUS_NUM_OF_TILE_MASK 0xF
+#define MFC_REG_DEC_STATUS_NUM_OF_TILE_SHIFT 15
+
+
+/* 0xF654: MFC_REG_D_DECODED_FRAME_TYPE */
+#define MFC_REG_DECODED_FRAME_MASK 0x7
+#define MFC_REG_DECODED_FRAME_NOT_CODED 0
+#define MFC_REG_DECODED_FRAME_I 1
+#define MFC_REG_DECODED_FRAME_P 2
+#define MFC_REG_DECODED_FRAME_B 3
+
+
+/* 0xF660: MFC_REG_D_DECODED_PICTURE_PROFILE */
+#define MFC_REG_D_DECODED_PIC_PROFILE_MASK 0x1F
+#define MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_MASK 0x7
+#define MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT 19
+#define MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_MASK 0x7
+#define MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_SHIFT 16
+#define MFC_REG_D_PROFILE_HEVC_MAIN 1
+#define MFC_REG_D_PROFILE_HEVC_MAIN_10 2
+#define MFC_REG_D_PROFILE_HEVC_RANGE_EXT 4
+
+
+/* 0xF684: MFC_REG_D_CHROMA_FORMAT */
+#define MFC_REG_D_CHROMA_FORMAT_MASK 0x3
+#define MFC_REG_D_COLOR_RANGE_MASK 0x1
+#define MFC_REG_D_COLOR_RANGE_SHIFT 3
+#define MFC_REG_D_COLOR_SPACE_MASK 0xF
+#define MFC_REG_D_COLOR_SPACE_SHIFT 4
+#define MFC_REG_D_COLOR_UNKNOWN 0
+#define MFC_REG_D_CHROMA_400 0
+#define MFC_REG_D_CHROMA_420 1
+#define MFC_REG_D_CHROMA_422 2
+#define MFC_REG_D_CHROMA_444 3
+
+
+/* 0xF690: MFC_REG_D_H264_INFO */
+#define MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT 9
+#define MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_MASK 0x1
+
+
+/* 0xF6D8: MFC_REG_D_MVC_VIEW_ID */
+#define MFC_REG_D_MVC_VIEW_ID_DISP_MASK 0xFFFF
+
+
+/* 0xF6DC: MFC_REG_D_SEI_AVAIL */
+#define MFC_REG_D_SEI_AVAIL_FRAME_PACK_MASK 0x1
+#define MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_MASK 0x1
+#define MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT 1
+#define MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK 0x1
+#define MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT 2
+
+
+/* 0xF70C: MFC_REG_D_VIDEO_SIGNAL_TYPE */
+#define MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_MASK 0x1
+#define MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT 29
+#define MFC_REG_D_COLOUR_DESCRIPTION_FLAG_MASK 0x1
+#define MFC_REG_D_COLOUR_DESCRIPTION_FLAG_SHIFT 24
+
+
+/* 0xF738: MFC_REG_D_BLACK_BAR_START_POS */
+#define MFC_REG_D_BLACK_BAR_START_X_SHIFT 0
+#define MFC_REG_D_BLACK_BAR_START_X_MASK 0xFFFF
+#define MFC_REG_D_BLACK_BAR_START_Y_SHIFT 16
+#define MFC_REG_D_BLACK_BAR_START_Y_MASK 0xFFFF
+
+
+/* 0xF73C: MFC_REG_D_BLACK_BAR_IMAGE_SIZE */
+#define MFC_REG_D_BLACK_BAR_IMAGE_W_SHIFT 0
+#define MFC_REG_D_BLACK_BAR_IMAGE_W_MASK 0xFFFF
+#define MFC_REG_D_BLACK_BAR_IMAGE_H_SHIFT 16
+#define MFC_REG_D_BLACK_BAR_IMAGE_H_MASK 0xFFFF
+
+
+/* 0xF780: MFC_REG_E_FRAME_CROP_OFFSET */
+#define MFC_REG_E_FRAME_CROP_OFFSET_TOP 16
+#define MFC_REG_E_FRAME_CROP_OFFSET_LEFT 0
+#define MFC_REG_E_FRAME_CROP_OFFSET_MASK 0x3FFF
+
+
+/* 0xF788: MFC_REG_E_PICTURE_PROFILE */
+#define MFC_REG_E_PROFILE_H264_BASELINE 0
+#define MFC_REG_E_PROFILE_H264_MAIN 1
+#define MFC_REG_E_PROFILE_H264_HIGH 2
+#define MFC_REG_E_PROFILE_H264_CONSTRAINED_BASELINE 3
+#define MFC_REG_E_PROFILE_H264_CONSTRAINED_HIGH 5
+#define MFC_REG_E_PROFILE_MPEG4_SIMPLE 0
+#define MFC_REG_E_PROFILE_MPEG4_ADVANCED_SIMPLE 1
+#define MFC_REG_E_PROFILE_HEVC_MAIN_422_10_INTRA 2
+#define MFC_REG_E_PROFILE_HEVC_MAIN_10 3
+#define MFC_REG_E_PROFILE_HEVC_MAIN_422_10 4
+#define MFC_REG_E_PROFILE_VP9_PROFILE0 0
+#define MFC_REG_E_PROFILE_VP9_PROFILE1 1
+#define MFC_REG_E_PROFILE_VP9_PROFILE2 2
+#define MFC_REG_E_PROFILE_VP9_PROFILE3 3
+
+
+/* 0xF7A4: MFC_REG_E_RC_MODE */
+#define MFC_REG_E_RC_CBR_FIX 0
+#define MFC_REG_E_RC_CBR_VAR 1
+#define MFC_REG_E_RC_VBR 2
+#define MFC_REG_E_RC_CBR_I_LIMIT 3
+
+
+/* 0xFA84: MFC_REG_E_SLICE_TYPE */
+#define MFC_REG_E_SLICE_TYPE_NOT_CODED 0
+#define MFC_REG_E_SLICE_TYPE_I 1
+#define MFC_REG_E_SLICE_TYPE_P 2
+#define MFC_REG_E_SLICE_TYPE_B 3
+#define MFC_REG_E_SLICE_TYPE_SKIPPED 4
+
+
+#endif /* __MFC_REGS_H */
+++ /dev/null
-/*
- * drivers/media/platform/exynos/mfc/regs-mfc-v10.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __REGS_MFC_V10_H
-#define __REGS_MFC_V10_H __FILE__
-
-#define MFC_MMU_INTERRUPT_STATUS 0x0060
-#define MFC_MMU_FAULT_TRANS_INFO 0x0078
-#define MFC_MMU_FAULT_TRANS_INFO_RW_MASK 0x100000
-#define MFC_MMU_FAULT_TRANS_INFO_AXID_MASK 0xFFFF
-
-#define HWFC_ENCODING_IDX 0x4
-
-/* Codec Common Registers */
-#define MFC_REG_RISC_ON 0x0000
-#define MFC_REG_RISC2HOST_INT 0x003C
-#define MFC_REG_HOST2RISC_INT 0x0044
-#define MFC_REG_RISC_BASE_ADDRESS 0x0054
-
-#define MFC_REG_MFC_FW_CLOCK 0x1060
-#define MFC_REG_MFC_RESET 0x1070
-
-#define MFC_REG_HOST2RISC_CMD 0x1100
-#define MFC_REG_RISC2HOST_CMD 0x1104
-
-#define MFC_REG_MFC_BUS_STATUS 0x7018
-#define MFC_REG_MFC_RPEND 0x7028
-#define MFC_REG_MFC_WPEND 0x702C
-#define MFC_REG_MFC_BUS_RESET_CTRL 0x7110
-#define MFC_REG_MFC_OFF 0x7120
-#define MFC_REG_MFC_STATE 0x7124
-
-#define MFC_REG_FW_VERSION 0xF000
-#define MFC_REG_INSTANCE_ID 0xF008
-#define MFC_REG_CODEC_TYPE 0xF00C
-#define MFC_REG_CONTEXT_MEM_ADDR 0xF014
-#define MFC_REG_CONTEXT_MEM_SIZE 0xF018
-#define MFC_REG_SHARED_MEM_ADDR 0xF01C
-#define MFC_REG_PIXEL_FORMAT 0xF020
-
-#define MFC_REG_METADATA_ENABLE 0xF024
-#define MFC_REG_MFC_VERSION 0xF028
-#define MFC_REG_DBG_INFO_ENABLE 0xF02C
-#define MFC_REG_DBG_BUFFER_ADDR 0xF030
-#define MFC_REG_DBG_BUFFER_SIZE 0xF034
-
-#define MFC_REG_CODEC_CONTROL 0xF038
-#define MFC_REG_DEC_TIMEOUT_VALUE 0xF03C
-#define MFC_REG_HED_SHARED_MEM_ADDR 0xF040
-
-/* NAL QUEUE */
-#define MFC_REG_NAL_QUEUE_INPUT_ADDR 0xF044
-#define MFC_REG_NAL_QUEUE_INPUT_SIZE 0xF048
-#define MFC_REG_NAL_QUEUE_OUTPUT_ADDR 0xF04C
-#define MFC_REG_NAL_QUEUE_OUTPUT_SIZE 0xF050
-#define MFC_REG_NAL_QUEUE_INPUT_COUNT 0xF054
-
-#define MFC_REG_RET_INSTANCE_ID 0xF070
-#define MFC_REG_ERROR_CODE 0xF074
-#define MFC_REG_DBG_BUFFER_OUTPUT_SIZE 0xF078
-#define MFC_REG_METADATA_STATUS 0xF07C
-
-#define MFC_REG_DBG_INFO_STAGE_COUNTER 0xF088
-
-/* NAL QUEUE */
-#define MFC_REG_NAL_QUEUE_OUTPUT_COUNT 0xF08C
-#define MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT 0xF090
-#define MFC_REG_NAL_QUEUE_INFO 0xF094
-
-/* Decoder Registers */
-#define MFC_REG_D_CRC_CTRL 0xF0B0
-#define MFC_REG_D_DEC_OPTIONS 0xF0B4
-
-#define MFC_REG_D_DISPLAY_DELAY 0xF0B8
-
-#define MFC_REG_D_SET_FRAME_WIDTH 0xF0BC
-#define MFC_REG_D_SET_FRAME_HEIGHT 0xF0C0
-
-#define MFC_REG_D_SEI_ENABLE 0xF0C4
-
-#define MFC_REG_D_FORCE_PIXEL_VAL 0xF0C8
-
-/* Buffer setting registers */
-/* Session return */
-#define MFC_REG_D_MIN_NUM_DPB 0xF0F0
-#define MFC_REG_D_MIN_FIRST_PLANE_DPB_SIZE 0xF0F4
-#define MFC_REG_D_MIN_SECOND_PLANE_DPB_SIZE 0xF0F8
-#define MFC_REG_D_MIN_THIRD_PLANE_DPB_SIZE 0xF0FC
-#define MFC_REG_D_MIN_NUM_MV 0xF100
-#define MFC_REG_D_MVC_NUM_VIEWS 0xF104
-#define MFC_REG_D_MIN_SCRATCH_BUFFER_SIZE 0xF108
-#define MFC_REG_D_MIN_FIRST_PLANE_2BIT_DPB_SIZE 0xF10C
-#define MFC_REG_D_MIN_SECOND_PLANE_2BIT_DPB_SIZE 0xF110
-#define MFC_REG_D_POST_FILTER_LUMA_DPB0 0xF120
-#define MFC_REG_D_POST_FILTER_LUMA_DPB1 0xF124
-#define MFC_REG_D_POST_FILTER_CHROMA_DPB0 0xF128
-#define MFC_REG_D_POST_FILTER_CHROMA_DPB1 0xF12C
-
-/* Buffers */
-#define MFC_REG_D_NUM_DPB 0xF130
-#define MFC_REG_D_NUM_MV 0xF134
-#define MFC_REG_D_FIRST_PLANE_DPB_STRIDE_SIZE 0xF138
-#define MFC_REG_D_SECOND_PLANE_DPB_STRIDE_SIZE 0xF13C
-#define MFC_REG_D_THIRD_PLANE_DPB_STRIDE_SIZE 0xF140
-#define MFC_REG_D_FIRST_PLANE_DPB_SIZE 0xF144
-#define MFC_REG_D_SECOND_PLANE_DPB_SIZE 0xF148
-#define MFC_REG_D_THIRD_PLANE_DPB_SIZE 0xF14C
-#define MFC_REG_D_MV_BUFFER_SIZE 0xF150
-#define MFC_REG_D_INIT_BUFFER_OPTIONS 0xF154
-#define MFC_REG_D_FIRST_PLANE_DPB0 0xF160
-#define MFC_REG_D_SECOND_PLANE_DPB0 0xF260
-#define MFC_REG_D_THIRD_PLANE_DPB0 0xF360
-#define MFC_REG_D_MV_BUFFER0 0xF460
-#define MFC_REG_D_SCRATCH_BUFFER_ADDR 0xF560
-#define MFC_REG_D_SCRATCH_BUFFER_SIZE 0xF564
-#define MFC_REG_D_METADATA_BUFFER_ADDR 0xF568
-#define MFC_REG_D_METADATA_BUFFER_SIZE 0xF56C
-
-#define MFC_REG_D_STATIC_BUFFER_ADDR 0xF570
-#define MFC_REG_D_STATIC_BUFFER_SIZE 0xF574
-#define MFC_REG_D_FIRST_PLANE_2BIT_DPB_SIZE 0xF578
-#define MFC_REG_D_SECOND_PLANE_2BIT_DPB_SIZE 0xF57C
-#define MFC_REG_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE 0xF580
-#define MFC_REG_D_SECOND_PLANE_2BIT_DPB_STRIDE_SIZE 0xF584
-
-#define MFC_REG_D_NAL_START_OPTIONS 0xF5AC
-
-/* Nal cmd */
-#define MFC_REG_D_CPB_BUFFER_ADDR 0xF5B0
-#define MFC_REG_D_CPB_BUFFER_SIZE 0xF5B4
-#define MFC_REG_D_AVAILABLE_DPB_FLAG_UPPER 0xF5B8
-#define MFC_REG_D_AVAILABLE_DPB_FLAG_LOWER 0xF5BC
-#define MFC_REG_D_CPB_BUFFER_OFFSET 0xF5C0
-#define MFC_REG_D_SLICE_IF_ENABLE 0xF5C4
-#define MFC_REG_D_PICTURE_TAG 0xF5C8
-#define MFC_REG_D_STREAM_DATA_SIZE 0xF5D0
-#define MFC_REG_D_DYNAMIC_DPB_FLAG_UPPER 0xF5D4
-#define MFC_REG_D_DYNAMIC_DPB_FLAG_LOWER 0xF5D8
-
-/* Nal return */
-#define MFC_REG_D_DISPLAY_FRAME_WIDTH 0xF600
-#define MFC_REG_D_DISPLAY_FRAME_HEIGHT 0xF604
-#define MFC_REG_D_DISPLAY_STATUS 0xF608
-#define MFC_REG_D_DISPLAY_FIRST_PLANE_ADDR 0xF60C
-#define MFC_REG_D_DISPLAY_SECOND_PLANE_ADDR 0xF610
-#define MFC_REG_D_DISPLAY_THIRD_PLANE_ADDR 0xF614
-#define MFC_REG_D_DISPLAY_FRAME_TYPE 0xF618
-#define MFC_REG_D_DISPLAY_CROP_INFO1 0xF61C
-#define MFC_REG_D_DISPLAY_CROP_INFO2 0xF620
-#define MFC_REG_D_DISPLAY_PICTURE_PROFILE 0xF624
-#define MFC_REG_D_DISPLAY_FIRST_PLANE_CRC 0xF628
-#define MFC_REG_D_DISPLAY_SECOND_PLANE_CRC 0xF62C
-#define MFC_REG_D_DISPLAY_THIRD_PLANE_CRC 0xF630
-#define MFC_REG_D_DISPLAY_ASPECT_RATIO 0xF634
-#define MFC_REG_D_DISPLAY_EXTENDED_AR 0xF638
-#define MFC_REG_D_DECODED_FRAME_WIDTH 0xF63C
-#define MFC_REG_D_DECODED_FRAME_HEIGHT 0xF640
-#define MFC_REG_D_DECODED_STATUS 0xF644
-#define MFC_REG_D_DECODED_FIRST_PLANE_ADDR 0xF648
-#define MFC_REG_D_DECODED_SECOND_PLANE_ADDR 0xF64C
-#define MFC_REG_D_DECODED_THIRD_PLANE_ADDR 0xF650
-#define MFC_REG_D_DECODED_FRAME_TYPE 0xF654
-#define MFC_REG_D_DECODED_CROP_INFO1 0xF658
-#define MFC_REG_D_DECODED_CROP_INFO2 0xF65C
-#define MFC_REG_D_DECODED_PICTURE_PROFILE 0xF660
-#define MFC_REG_D_DECODED_NAL_SIZE 0xF664
-#define MFC_REG_D_DECODED_FIRST_PLANE_CRC 0xF668
-#define MFC_REG_D_DECODED_SECOND_PLANE_CRC 0xF66C
-#define MFC_REG_D_DECODED_THIRD_PLANE_CRC 0xF670
-#define MFC_REG_D_RET_PICTURE_TAG_TOP 0xF674
-#define MFC_REG_D_RET_PICTURE_TAG_BOT 0xF678
-#define MFC_REG_D_RET_PICTURE_TIME_TOP 0xF67C
-#define MFC_REG_D_RET_PICTURE_TIME_BOT 0xF680
-#define MFC_REG_D_CHROMA_FORMAT 0xF684
-
-#define MFC_REG_D_VC1_INFO 0xF688
-#define MFC_REG_D_MPEG4_INFO 0xF68C
-#define MFC_REG_D_H264_INFO 0xF690
-#define MFC_REG_D_HEVC_INFO 0xF6A0
-#define MFC_REG_D_BPG_INFO 0xF6A8
-
-#define MFC_REG_D_METADATA_ADDR_CONCEALED_MB 0xF6B0
-#define MFC_REG_D_METADATA_SIZE_CONCEALED_MB 0xF6B4
-#define MFC_REG_D_METADATA_ADDR_VC1_PARAM 0xF6B8
-#define MFC_REG_D_METADATA_SIZE_VC1_PARAM 0xF6BC
-#define MFC_REG_D_METADATA_ADDR_SEI_NAL 0xF6C0
-#define MFC_REG_D_METADATA_SIZE_SEI_NAL 0xF6C4
-#define MFC_REG_D_METADATA_ADDR_VUI 0xF6C8
-#define MFC_REG_D_METADATA_SIZE_VUI 0xF6CC
-#define MFC_REG_D_METADATA_ADDR_MVCVUI 0xF6D0
-#define MFC_REG_D_METADATA_SIZE_MVCVUI 0xF6D4
-
-#define MFC_REG_D_MVC_VIEW_ID 0xF6D8
-
-#define MFC_REG_D_SEI_AVAIL 0xF6DC
-#define MFC_REG_D_FRAME_PACK_ARRGMENT_ID 0xF6E0
-#define MFC_REG_D_FRAME_PACK_SEI_INFO 0xF6E4
-#define MFC_REG_D_FRAME_PACK_GRID_POS 0xF6E8
-
-#define MFC_REG_D_DISPLAY_RECOVERY_SEI_INFO 0xF6EC
-#define MFC_REG_D_DECODED_RECOVERY_SEI_INFO 0xF6F0
-
-#define MFC_REG_D_DISPLAY_FIRST_PLANE_2BIT_CRC 0xF6FC
-#define MFC_REG_D_DISPLAY_SECOND_PLANE_2BIT_CRC 0xF700
-#define MFC_REG_D_DECODED_FIRST_PLANE_2BIT_CRC 0xF704
-#define MFC_REG_D_DECODED_SECOND_PLANE_2BIT_CRC 0xF708
-
-#define MFC_REG_D_VIDEO_SIGNAL_TYPE 0xF70C
-#define MFC_REG_D_CONTENT_LIGHT_LEVEL_INFO_SEI 0xF710
-#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0 0xF714
-#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1 0xF718
-
-#define MFC_REG_D_USED_DPB_FLAG_UPPER 0xF720
-#define MFC_REG_D_USED_DPB_FLAG_LOWER 0xF724
-
-#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2 0xF728
-#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3 0xF72C
-#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4 0xF730
-#define MFC_REG_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5 0xF734
-
-#define MFC_REG_D_BLACK_BAR_START_POS 0xF738
-#define MFC_REG_D_BLACK_BAR_IMAGE_SIZE 0xF73C
-
-#define MFC_REG_D_DISPLAY_LUMA_ADDR 0xF60C
-#define MFC_REG_D_DISPLAY_CHROMA_ADDR 0xF610
-
-#define MFC_REG_D_DECODED_LUMA_ADDR 0xF648
-#define MFC_REG_D_DECODED_CHROMA_ADDR 0xF64C
-
-/* Encoder Registers */
-#define MFC_REG_E_CROPPED_FRAME_WIDTH 0xF778
-#define MFC_REG_E_CROPPED_FRAME_HEIGHT 0xF77C
-#define MFC_REG_E_FRAME_CROP_OFFSET 0xF780
-#define MFC_REG_E_ENC_OPTIONS 0xF784
-#define MFC_REG_E_PICTURE_PROFILE 0xF788
-#define MFC_REG_E_VBV_BUFFER_SIZE 0xF78C
-#define MFC_REG_E_VBV_INIT_DELAY 0xF790
-#define MFC_REG_E_FIXED_PICTURE_QP 0xF794
-#define MFC_REG_E_RC_CONFIG 0xF798
-#define MFC_REG_E_RC_QP_BOUND 0xF79C
-#define MFC_REG_E_RC_QP_BOUND_PB 0xF7A0
-#define MFC_REG_E_RC_MODE 0xF7A4
-
-#define MFC_REG_E_MB_RC_CONFIG 0xF7A8
-#define MFC_REG_E_PADDING_CTRL 0xF7AC
-#define MFC_REG_E_AIR_THRESHOLD 0xF7B0
-
-#define MFC_REG_E_MV_HOR_RANGE 0xF7B4
-#define MFC_REG_E_MV_VER_RANGE 0xF7B8
-
-#define MFC_REG_E_HIGH_QUALITY_MODE 0xF7C0
-#define MFC_REG_E_VIDEO_SIGNAL_TYPE 0xF7C4
-
-#define MFC_REG_E_SAO_WEIGHT0 0xF7C8
-#define MFC_REG_E_SAO_WEIGHT1 0xF7CC
-
-#define MFC_REG_E_NUM_DPB 0xF890
-#define MFC_REG_E_MIN_SCRATCH_BUFFER_SIZE 0xF894
-
-#define MFC_REG_E_LUMA_DPB 0xF8C0
-#define MFC_REG_E_CHROMA_DPB 0xF904
-#define MFC_REG_E_ME_BUFFER 0xF948
-
-#define MFC_REG_E_SCRATCH_BUFFER_ADDR 0xF98C
-#define MFC_REG_E_SCRATCH_BUFFER_SIZE 0xF990
-#define MFC_REG_E_TMV_BUFFER0 0xF994
-#define MFC_REG_E_TMV_BUFFER1 0xF998
-#define MFC_REG_E_IR_BUFFER_ADDR 0xF99C
-#define MFC_REG_E_SOURCE_FIRST_2BIT_ADDR 0xF9D0
-#define MFC_REG_E_SOURCE_SECOND_2BIT_ADDR 0xF9D4
-#define MFC_REG_E_SOURCE_FIRST_2BIT_STRIDE 0xF9D8
-#define MFC_REG_E_SOURCE_SECOND_2BIT_STRIDE 0xF9DC
-#define MFC_REG_E_SOURCE_FIRST_ADDR 0xF9E0
-#define MFC_REG_E_SOURCE_SECOND_ADDR 0xF9E4
-#define MFC_REG_E_SOURCE_THIRD_ADDR 0xF9E8
-#define MFC_REG_E_SOURCE_FIRST_STRIDE 0xF9EC
-#define MFC_REG_E_SOURCE_SECOND_STRIDE 0xF9F0
-#define MFC_REG_E_SOURCE_THIRD_STRIDE 0xF9F4
-#define MFC_REG_E_STREAM_BUFFER_ADDR 0xF9F8
-#define MFC_REG_E_STREAM_BUFFER_SIZE 0xF9FC
-#define MFC_REG_E_ROI_BUFFER_ADDR 0xFA00
-
-#define MFC_REG_E_PARAM_CHANGE 0xFA04
-#define MFC_REG_E_IR_SIZE 0xFA08
-#define MFC_REG_E_GOP_CONFIG 0xFA0C
-#define MFC_REG_E_MSLICE_MODE 0xFA10
-#define MFC_REG_E_MSLICE_SIZE_MB 0xFA14
-#define MFC_REG_E_MSLICE_SIZE_BITS 0xFA18
-#define MFC_REG_E_FRAME_INSERTION 0xFA1C
-
-#define MFC_REG_E_RC_FRAME_RATE 0xFA20
-#define MFC_REG_E_RC_BIT_RATE 0xFA24
-#define MFC_REG_E_RC_ROI_CTRL 0xFA2C
-#define MFC_REG_E_PICTURE_TAG 0xFA30
-#define MFC_REG_E_BIT_COUNT_ENABLE 0xFA34
-#define MFC_REG_E_MAX_BIT_COUNT 0xFA38
-#define MFC_REG_E_MIN_BIT_COUNT 0xFA3C
-
-#define MFC_REG_E_METADATA_BUFFER_ADDR 0xFA40
-#define MFC_REG_E_METADATA_BUFFER_SIZE 0xFA44
-
-#define MFC_REG_E_ENCODING_ORDER_TIME_INFO 0xFA50
-#define MFC_REG_E_ENCODING_ORDER_INFO 0xFA54
-#define MFC_REG_E_STREAM_BUFFER_OFFSET 0xFA58
-#define MFC_REG_E_GOP_CONFIG2 0xFA5C
-#define MFC_REG_E_WEIGHT_FOR_WEIGHTED_PREDICTION 0xFA60
-
-#define MFC_REG_E_ENCODED_SOURCE_FIRST_ADDR 0xFA70
-#define MFC_REG_E_ENCODED_SOURCE_SECOND_ADDR 0xFA74
-#define MFC_REG_E_ENCODED_SOURCE_THIRD_ADDR 0xFA78
-
-#define MFC_REG_E_STREAM_SIZE 0xFA80
-#define MFC_REG_E_SLICE_TYPE 0xFA84
-#define MFC_REG_E_PICTURE_COUNT 0xFA88
-#define MFC_REG_E_RET_PICTURE_TAG 0xFA8C
-
-#define MFC_REG_E_RECON_LUMA_DPB_ADDR 0xFA9C
-#define MFC_REG_E_RECON_CHROMA_DPB_ADDR 0xFAA0
-#define MFC_REG_E_METADATA_ADDR_ENC_SLICE 0xFAA4
-#define MFC_REG_E_METADATA_SIZE_ENC_SLICE 0xFAA8
-
-#define MFC_REG_E_NAL_DONE_INFO 0xFAEC
-
-#define MFC_REG_E_MPEG4_OPTIONS 0xFB10
-#define MFC_REG_E_MPEG4_HEC_PERIOD 0xFB14
-
-#define MFC_REG_E_BPG_OPTIONS 0xFB1C
-#define MFC_REG_E_BPG_EXT_CTB_QP_CTRL 0xFB20
-#define MFC_REG_E_BPG_CHROMA_QP_OFFSET 0xFB24
-#define MFC_REG_E_BPG_EXTENSION_DATA_SIZE 0xFB28
-
-#define MFC_REG_E_H264_HD_SVC_EXTENSION_0 0xFB44
-#define MFC_REG_E_H264_HD_SVC_EXTENSION_1 0xFB48
-#define MFC_REG_E_ASPECT_RATIO 0xFB4C
-#define MFC_REG_E_EXTENDED_SAR 0xFB50
-
-#define MFC_REG_E_H264_OPTIONS 0xFB54
-#define MFC_REG_E_H264_OPTIONS_2 0xFB58
-#define MFC_REG_E_H264_LF_ALPHA_OFFSET 0xFB5C
-#define MFC_REG_E_H264_LF_BETA_OFFSET 0xFB60
-#define MFC_REG_E_H264_REFRESH_PERIOD 0xFB64
-
-#define MFC_REG_E_H264_FMO_SLICE_GRP_MAP_TYPE 0xFB68
-#define MFC_REG_E_H264_FMO_NUM_SLICE_GRP_MINUS1 0xFB6C
-#define MFC_REG_E_H264_FMO_SLICE_GRP_CHANGE_DIR 0xFB70
-#define MFC_REG_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1 0xFB74
-#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_0 0xFB78
-#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_1 0xFB7C
-#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_2 0xFB80
-#define MFC_REG_E_H264_FMO_RUN_LENGTH_MINUS1_3 0xFB84
-
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_0 0xFB88
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_1 0xFB8C
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_2 0xFB90
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_3 0xFB94
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_4 0xFB98
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_5 0xFB9C
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_6 0xFBA0
-#define MFC_REG_E_H264_ASO_SLICE_ORDER_7 0xFBA4
-#define MFC_REG_E_H264_CHROMA_QP_OFFSET 0xFBA8
-
-#define MFC_REG_E_NUM_T_LAYER 0xFBAC
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER0 0xFBB0
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER1 0xFBB4
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER2 0xFBB8
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER3 0xFBBC
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER4 0xFBC0
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER5 0xFBC4
-#define MFC_REG_E_HIERARCHICAL_QP_LAYER6 0xFBC8
-
-/* For backward compatibility */
-#define MFC_REG_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
-
-#define MFC_REG_E_H264_NAL_CONTROL 0xFD14
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER0 0xFD18
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER1 0xFD1C
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER2 0xFD20
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER3 0xFD24
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER4 0xFD28
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER5 0xFD2C
-#define MFC_REG_E_HIERARCHICAL_BIT_RATE_LAYER6 0xFD30
-
-#define MFC_REG_E_MVC_FRAME_QP_VIEW1 0xFD40
-#define MFC_REG_E_MVC_RC_FRAME_RATE_VIEW1 0xFD44
-#define MFC_REG_E_MVC_RC_BIT_RATE_VIEW1 0xFD48
-#define MFC_REG_E_MVC_RC_QBOUND_VIEW1 0xFD4C
-#define MFC_REG_E_MVC_RC_MODE_VIEW1 0xFD50
-#define MFC_REG_E_MVC_INTER_VIEW_PREDICTION_ON 0xFD80
-
-#define MFC_REG_E_VP9_OPTION 0xFD90
-#define MFC_REG_E_VP9_FILTER_OPTION 0xFD94
-#define MFC_REG_E_VP9_GOLDEN_FRAME_OPTION 0xFD98
-#define MFC_REG_E_VP8_OPTION 0xFDB0
-#define MFC_REG_E_VP8_FILTER_OPTION 0xFDB4
-#define MFC_REG_E_VP8_GOLDEN_FRAME_OPTION 0xFDB8
-
-#define MFC_REG_E_HEVC_OPTIONS_2 0xFDC4
-
-#define MFC_REG_E_HEVC_OPTIONS 0xFDD4
-#define MFC_REG_E_HEVC_REFRESH_PERIOD 0xFDD8
-#define MFC_REG_E_HEVC_CHROMA_QP_OFFSET 0xFDDC
-#define MFC_REG_E_HEVC_LF_BETA_OFFSET_DIV2 0xFDE0
-#define MFC_REG_E_HEVC_LF_TC_OFFSET_DIV2 0xFDE4
-#define MFC_REG_E_HEVC_NAL_CONTROL 0xFDE8
-
-#define MFC_REG_E_VP8_NAL_CONTROL 0xFDF0
-#define MFC_REG_E_VP9_NAL_CONTROL 0xFDF4
-#define MFC_REG_E_CONTENT_LIGHT_LEVEL_INFO_SEI 0xFDF8
-#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0 0xFDFC
-#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1 0xFE00
-#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2 0xFE04
-#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3 0xFE08
-#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4 0xFE0C
-#define MFC_REG_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5 0xFE10
-
-
-#define MFC_REG_REG_CLEAR_BEGIN 0xf000
-#define MFC_REG_REG_CLEAR_COUNT 1024
-
-
-/* Bit Definitions */
-/* 0x1100: MFC_REG_HOST2RISC_CMD */
-#define MFC_REG_H2R_CMD_EMPTY 0
-#define MFC_REG_H2R_CMD_SYS_INIT 1
-#define MFC_REG_H2R_CMD_OPEN_INSTANCE 2
-#define MFC_REG_H2R_CMD_SEQ_HEADER 3
-#define MFC_REG_H2R_CMD_INIT_BUFFERS 4
-#define MFC_REG_H2R_CMD_NAL_START 5
-#define MFC_REG_H2R_CMD_CLOSE_INSTANCE 6
-#define MFC_REG_H2R_CMD_SLEEP 7
-#define MFC_REG_H2R_CMD_WAKEUP 8
-#define MFC_REG_H2R_CMD_LAST_FRAME 9
-#define MFC_REG_H2R_CMD_DPB_FLUSH 10
-#define MFC_REG_H2R_CMD_NAL_ABORT 11
-#define MFC_REG_H2R_CMD_CACHE_FLUSH 12
-#define MFC_REG_H2R_CMD_NAL_QUEUE 13
-#define MFC_REG_H2R_CMD_STOP_QUEUE 14
-
-
-/* 0x1104: MFC_REG_RISC2HOST_CMD */
-#define MFC_REG_RISC2HOST_CMD_MASK 0x1FFFF
-#define MFC_REG_R2H_CMD_EMPTY 0
-#define MFC_REG_R2H_CMD_SYS_INIT_RET 1
-#define MFC_REG_R2H_CMD_OPEN_INSTANCE_RET 2
-#define MFC_REG_R2H_CMD_SEQ_DONE_RET 3
-#define MFC_REG_R2H_CMD_INIT_BUFFERS_RET 4
-#define MFC_REG_R2H_CMD_CLOSE_INSTANCE_RET 6
-#define MFC_REG_R2H_CMD_SLEEP_RET 7
-#define MFC_REG_R2H_CMD_WAKEUP_RET 8
-#define MFC_REG_R2H_CMD_COMPLETE_SEQ_RET 9
-#define MFC_REG_R2H_CMD_DPB_FLUSH_RET 10
-#define MFC_REG_R2H_CMD_NAL_ABORT_RET 11
-#define MFC_REG_R2H_CMD_FW_STATUS_RET 12
-#define MFC_REG_R2H_CMD_FRAME_DONE_RET 13
-#define MFC_REG_R2H_CMD_FIELD_DONE_RET 14
-#define MFC_REG_R2H_CMD_SLICE_DONE_RET 15
-#define MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET 16
-#define MFC_REG_R2H_CMD_QUEUE_DONE_RET 17
-#define MFC_REG_R2H_CMD_COMPLETE_QUEUE_RET 18
-#define MFC_REG_R2H_CMD_CACHE_FLUSH_RET 20
-#define MFC_REG_R2H_CMD_ERR_RET 32
-
-
-/* 0xF000: MFC_REG_FW_VERSION */
-#define MFC_REG_FW_VER_INFO_MASK 0xFF
-#define MFC_REG_FW_VER_INFO_SHFT 24
-#define MFC_REG_FW_VER_YEAR_MASK 0xFF
-#define MFC_REG_FW_VER_YEAR_SHFT 16
-#define MFC_REG_FW_VER_MONTH_MASK 0xFF
-#define MFC_REG_FW_VER_MONTH_SHFT 8
-#define MFC_REG_FW_VER_DATE_MASK 0xFF
-#define MFC_REG_FW_VER_DATE_SHFT 0
-#define MFC_REG_FW_VER_ALL_MASK 0xFFFFFF
-#define MFC_REG_FW_VER_ALL_SHFT 0
-
-
-/* 0xF00C: MFC_REG_CODEC_TYPE */
-#define MFC_FORMATS_NO_CODEC -1
-/* Decoder */
-#define MFC_REG_CODEC_H264_DEC 0
-#define MFC_REG_CODEC_H264_MVC_DEC 1
-#define MFC_REG_CODEC_MPEG4_DEC 3
-#define MFC_REG_CODEC_FIMV1_DEC 4
-#define MFC_REG_CODEC_FIMV2_DEC 5
-#define MFC_REG_CODEC_FIMV3_DEC 6
-#define MFC_REG_CODEC_FIMV4_DEC 7
-#define MFC_REG_CODEC_H263_DEC 8
-#define MFC_REG_CODEC_VC1_RCV_DEC 9
-#define MFC_REG_CODEC_VC1_DEC 10
-#define MFC_REG_CODEC_MPEG2_DEC 13
-#define MFC_REG_CODEC_VP8_DEC 14
-#define MFC_REG_CODEC_HEVC_DEC 17
-#define MFC_REG_CODEC_VP9_DEC 18
-/* Encoder */
-#define MFC_REG_CODEC_H264_ENC 20
-#define MFC_REG_CODEC_H264_MVC_ENC 21
-#define MFC_REG_CODEC_MPEG4_ENC 23
-#define MFC_REG_CODEC_H263_ENC 24
-#define MFC_REG_CODEC_VP8_ENC 25
-#define MFC_REG_CODEC_HEVC_ENC 26
-#define MFC_REG_CODEC_VP9_ENC 27
-
-#define MFC_REG_CODEC_BPG_DEC 32
-#define MFC_REG_CODEC_BPG_ENC 33
-
-/* 0xF028: MFC_REG_MFC_VERSION */
-#define MFC_REG_MFC_VER_MASK 0xFFFFFFFF
-#define MFC_REG_MFC_VER_SHFT 0
-
-
-/* 0xF074: MFC_REG_ERROR_CODE */
-#define MFC_REG_ERR_STATUS_MASK 0xFFFF
-#define MFC_REG_ERR_STATUS_SHIFT 0
-#define MFC_REG_WARN_STATUS_MASK 0xFFFF
-#define MFC_REG_WARN_STATUS_SHIFT 16
-/* Error number */
-#define MFC_REG_ERR_BUFFER_FULL 18
-#define MFC_REG_ERR_NO_AVAILABLE_DPB 33
-#define MFC_REG_ERR_NO_KEY_FRAME 34
-#define MFC_REG_ERR_VPS_ONLY_ERROR 42
-#define MFC_REG_ERR_INSUFFICIENT_DPB_SIZE 57
-#define MFC_REG_ERR_INSUFFICIENT_NUM_DPB 58
-#define MFC_REG_ERR_INSUFFICIENT_MV_BUF_SIZE 60
-#define MFC_REG_ERR_NULL_SCRATCH 61
-#define MFC_REG_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE 62
-
-#define MFC_REG_ERR_UNSUPPORTED_FEATURE 100
-#define MFC_REG_ERR_UNSUPPORTED_RESOLUTION 101
-#define MFC_REG_ERR_HEADER_NOT_FOUND 102
-#define MFC_REG_ERR_INVAILD_NAL_TYPE 103
-#define MFC_REG_ERR_SEQUENCE_HEADER 104
-#define MFC_REG_ERR_MFC_TIMEOUT 140
-#define MFC_REG_ERR_TS_MUX_TIMEOUT 141
-#define MFC_REG_ERR_G2D_TIMEOUT 142
-#define MFC_REG_ERR_FRAME_CONCEAL 150
-#define MFC_REG_ERR_WARNINGS_START 160
-#define MFC_REG_ERR_BROKEN_LINK 161
-#define MFC_REG_ERR_SYNC_POINT_NOT_RECEIVED 190
-#define MFC_REG_ERR_NON_PAIRED_FIELD 191
-#define MFC_REG_ERR_WARNINGS_END 222
-
-
-/* 0xF0B4: MFC_REG_D_DEC_OPTIONS */
-#define MFC_REG_D_DEC_OPT_DISPLAY_DELAY_EN_SHIFT 3
-#define MFC_REG_D_DEC_OPT_FMO_ASO_CTRL_MASK 0x1
-#define MFC_REG_D_DEC_OPT_FMO_ASO_CTRL_SHIFT 4
-#define MFC_REG_D_DEC_OPT_IDR_DECODING_MASK 0x1
-#define MFC_REG_D_DEC_OPT_IDR_DECODING_SHIFT 6
-#define MFC_REG_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT 7
-#define MFC_REG_D_DEC_OPT_CONCEAL_CONTROL_SHIFT 8
-#define MFC_REG_D_DEC_OPT_PARALLEL_DISABLE_SHIFT 11
-#define MFC_REG_D_DEC_OPT_REALLOC_CONTROL_SHIFT 13
-#define MFC_REG_D_DEC_OPT_SPECIAL_PARSING_SHIFT 15
-#define MFC_REG_D_DEC_OPT_THUMBNAIL_DECODING 16
-
-
-/* 0xF0C4: MFC_REG_D_SEI_ENABLE */
-#define MFC_REG_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT 1
-#define MFC_REG_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT 2
-#define MFC_REG_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT 4
-#define MFC_REG_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT 5
-
-
-/* 0xF154: MFC_REG_D_INIT_BUFFER_OPTIONS */
-#define MFC_REG_D_INIT_BUF_OPT_LF_CTRL_MASK 0x3
-#define MFC_REG_D_INIT_BUF_OPT_LF_CTRL_SHIFT 1
-#define MFC_REG_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT 3
-#define MFC_REG_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT 4
-#define MFC_REG_D_INIT_BUF_OPT_DITHERING_EN_SHIFT 6
-#define MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN 7
-
-
-/* 0xF5AC: MFC_REG_D_NAL_START_OPTIONS */
-#define MFC_REG_D_NAL_START_OPT_BLACK_BAR_SHIFT 3
-
-
-/* 0xF608: MFC_REG_D_DISPLAY_STATUS */
-#define MFC_REG_DISP_STATUS_DISPLAY_STATUS_MASK 0x7
-#define MFC_REG_DISP_STATUS_INTERLACE_MASK 0x1
-#define MFC_REG_DISP_STATUS_INTERLACE_SHIFT 3
-#define MFC_REG_DISP_STATUS_RES_CHANGE_MASK 0x3
-#define MFC_REG_DISP_STATUS_RES_CHANGE_SHIFT 4
-#define MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_MASK 0x1
-#define MFC_REG_DISP_STATUS_NEED_DPB_CHANGE_SHIFT 9
-#define MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK 0x1
-#define MFC_REG_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT 10
-#define MFC_REG_DISP_STATUS_NEED_EMPTY_DPB_MASK 0x1
-#define MFC_REG_DISP_STATUS_NEED_EMPTY_DPB_SHIFT 12
-#define MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_MASK 0x3
-#define MFC_REG_DISP_STATUS_BLACK_BAR_DETECT_SHIFT 13
-#define MFC_REG_DISP_STATUS_NOT_DETECTED 0x0
-#define MFC_REG_DISP_STATUS_BLACK_BAR 0x1
-#define MFC_REG_DISP_STATUS_BLACK_SCREEN 0x2
-
-
-/* 0xF618: MFC_REG_D_DISPLAY_FRAME_TYPE */
-#define MFC_REG_DISPLAY_FRAME_MASK 0x7
-#define MFC_REG_DISPLAY_TEMP_INFO_MASK 0x1
-#define MFC_REG_DISPLAY_TEMP_INFO_SHIFT 7
-#define MFC_REG_DISPLAY_FRAME_NOT_CODED 0
-#define MFC_REG_DISPLAY_FRAME_I 1
-#define MFC_REG_DISPLAY_FRAME_P 2
-#define MFC_REG_DISPLAY_FRAME_B 3
-
-
-/* 0xF61C: MFC_REG_D_DISPLAY_CROP_INFO1 */
-#define MFC_REG_D_SHARED_CROP_LEFT_MASK 0xFFFF
-#define MFC_REG_D_SHARED_CROP_RIGHT_SHIFT 16
-
-
-/* 0xF620: MFC_REG_D_DISPLAY_CROP_INFO2 */
-#define MFC_REG_D_SHARED_CROP_TOP_MASK 0xFFFF
-#define MFC_REG_D_SHARED_CROP_BOTTOM_SHIFT 16
-
-
-/* 0xF644: MFC_REG_D_DECODED_STATUS */
-#define MFC_REG_DEC_STATUS_DECODED_STATUS_MASK 0x7
-#define MFC_REG_DEC_STATUS_DECODING_ONLY 0
-#define MFC_REG_DEC_STATUS_DECODING_DISPLAY 1
-#define MFC_REG_DEC_STATUS_DISPLAY_ONLY 2
-#define MFC_REG_DEC_STATUS_DECODING_EMPTY 3
-#define MFC_REG_DEC_STATUS_NUM_OF_TILE_MASK 0xF
-#define MFC_REG_DEC_STATUS_NUM_OF_TILE_SHIFT 15
-
-
-/* 0xF654: MFC_REG_D_DECODED_FRAME_TYPE */
-#define MFC_REG_DECODED_FRAME_MASK 0x7
-#define MFC_REG_DECODED_FRAME_NOT_CODED 0
-#define MFC_REG_DECODED_FRAME_I 1
-#define MFC_REG_DECODED_FRAME_P 2
-#define MFC_REG_DECODED_FRAME_B 3
-
-
-/* 0xF660: MFC_REG_D_DECODED_PICTURE_PROFILE */
-#define MFC_REG_D_DECODED_PIC_PROFILE_MASK 0x1F
-#define MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_MASK 0x7
-#define MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT 19
-#define MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_MASK 0x7
-#define MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_SHIFT 16
-#define MFC_REG_D_PROFILE_HEVC_MAIN 1
-#define MFC_REG_D_PROFILE_HEVC_MAIN_10 2
-#define MFC_REG_D_PROFILE_HEVC_RANGE_EXT 4
-
-
-/* 0xF684: MFC_REG_D_CHROMA_FORMAT */
-#define MFC_REG_D_CHROMA_FORMAT_MASK 0x3
-#define MFC_REG_D_COLOR_RANGE_MASK 0x1
-#define MFC_REG_D_COLOR_RANGE_SHIFT 3
-#define MFC_REG_D_COLOR_SPACE_MASK 0xF
-#define MFC_REG_D_COLOR_SPACE_SHIFT 4
-#define MFC_REG_D_COLOR_UNKNOWN 0
-#define MFC_REG_D_CHROMA_400 0
-#define MFC_REG_D_CHROMA_420 1
-#define MFC_REG_D_CHROMA_422 2
-#define MFC_REG_D_CHROMA_444 3
-
-
-/* 0xF690: MFC_REG_D_H264_INFO */
-#define MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT 9
-#define MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_MASK 0x1
-
-
-/* 0xF6D8: MFC_REG_D_MVC_VIEW_ID */
-#define MFC_REG_D_MVC_VIEW_ID_DISP_MASK 0xFFFF
-
-
-/* 0xF6DC: MFC_REG_D_SEI_AVAIL */
-#define MFC_REG_D_SEI_AVAIL_FRAME_PACK_MASK 0x1
-#define MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_MASK 0x1
-#define MFC_REG_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT 1
-#define MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK 0x1
-#define MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT 2
-
-
-/* 0xF70C: MFC_REG_D_VIDEO_SIGNAL_TYPE */
-#define MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_MASK 0x1
-#define MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT 29
-#define MFC_REG_D_COLOUR_DESCRIPTION_FLAG_MASK 0x1
-#define MFC_REG_D_COLOUR_DESCRIPTION_FLAG_SHIFT 24
-
-
-/* 0xF738: MFC_REG_D_BLACK_BAR_START_POS */
-#define MFC_REG_D_BLACK_BAR_START_X_SHIFT 0
-#define MFC_REG_D_BLACK_BAR_START_X_MASK 0xFFFF
-#define MFC_REG_D_BLACK_BAR_START_Y_SHIFT 16
-#define MFC_REG_D_BLACK_BAR_START_Y_MASK 0xFFFF
-
-
-/* 0xF73C: MFC_REG_D_BLACK_BAR_IMAGE_SIZE */
-#define MFC_REG_D_BLACK_BAR_IMAGE_W_SHIFT 0
-#define MFC_REG_D_BLACK_BAR_IMAGE_W_MASK 0xFFFF
-#define MFC_REG_D_BLACK_BAR_IMAGE_H_SHIFT 16
-#define MFC_REG_D_BLACK_BAR_IMAGE_H_MASK 0xFFFF
-
-
-/* 0xF780: MFC_REG_E_FRAME_CROP_OFFSET */
-#define MFC_REG_E_FRAME_CROP_OFFSET_TOP 16
-#define MFC_REG_E_FRAME_CROP_OFFSET_LEFT 0
-#define MFC_REG_E_FRAME_CROP_OFFSET_MASK 0x3FFF
-
-
-/* 0xF788: MFC_REG_E_PICTURE_PROFILE */
-#define MFC_REG_E_PROFILE_H264_BASELINE 0
-#define MFC_REG_E_PROFILE_H264_MAIN 1
-#define MFC_REG_E_PROFILE_H264_HIGH 2
-#define MFC_REG_E_PROFILE_H264_CONSTRAINED_BASELINE 3
-#define MFC_REG_E_PROFILE_H264_CONSTRAINED_HIGH 5
-#define MFC_REG_E_PROFILE_MPEG4_SIMPLE 0
-#define MFC_REG_E_PROFILE_MPEG4_ADVANCED_SIMPLE 1
-#define MFC_REG_E_PROFILE_HEVC_MAIN_422_10_INTRA 2
-#define MFC_REG_E_PROFILE_HEVC_MAIN_10 3
-#define MFC_REG_E_PROFILE_HEVC_MAIN_422_10 4
-#define MFC_REG_E_PROFILE_VP9_PROFILE0 0
-#define MFC_REG_E_PROFILE_VP9_PROFILE1 1
-#define MFC_REG_E_PROFILE_VP9_PROFILE2 2
-#define MFC_REG_E_PROFILE_VP9_PROFILE3 3
-
-
-/* 0xF7A4: MFC_REG_E_RC_MODE */
-#define MFC_REG_E_RC_CBR_FIX 0
-#define MFC_REG_E_RC_CBR_VAR 1
-#define MFC_REG_E_RC_VBR 2
-#define MFC_REG_E_RC_CBR_I_LIMIT 3
-
-
-/* 0xFA84: MFC_REG_E_SLICE_TYPE */
-#define MFC_REG_E_SLICE_TYPE_NOT_CODED 0
-#define MFC_REG_E_SLICE_TYPE_I 1
-#define MFC_REG_E_SLICE_TYPE_P 2
-#define MFC_REG_E_SLICE_TYPE_B 3
-#define MFC_REG_E_SLICE_TYPE_SKIPPED 4
-
-
-#endif /* __REGS_MFC_V10_H */
#include "mfc_sync.h"
-#include "mfc_cal.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_perf_measure.h"
#include "mfc_queue.h"
#include "mfc_pm.h"
#include "mfc_cmd.h"
-#include "mfc_cal.h"
-#include "mfc_reg.h"
+#include "mfc_reg_api.h"
+#include "mfc_hw_reg_api.h"
#include "mfc_queue.h"
#include "mfc_utils.h"