From: Sunyoung Kang Date: Tue, 26 Jun 2018 06:10:09 +0000 (+0900) Subject: [COMMON] media: mfc: DRV4.0: change to intuitive file name. X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f7dedd10c4ecefb891f74469a26ffa55f7def1ca;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] media: mfc: DRV4.0: change to intuitive file name. 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 --- diff --git a/drivers/media/platform/exynos/mfc/Makefile b/drivers/media/platform/exynos/mfc/Makefile index 72eddaeb1112..40c8cf76551e 100644 --- a/drivers/media/platform/exynos/mfc/Makefile +++ b/drivers/media/platform/exynos/mfc/Makefile @@ -1,8 +1,8 @@ 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 diff --git a/drivers/media/platform/exynos/mfc/mfc.c b/drivers/media/platform/exynos/mfc/mfc.c index 5aef071bd3eb..8f5e8d3eedc3 100644 --- a/drivers/media/platform/exynos/mfc/mfc.c +++ b/drivers/media/platform/exynos/mfc/mfc.c @@ -23,9 +23,9 @@ #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" @@ -38,9 +38,9 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_cal.c b/drivers/media/platform/exynos/mfc/mfc_cal.c deleted file mode 100644 index 56f9a1c6fee6..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_cal.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 - -#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; -} diff --git a/drivers/media/platform/exynos/mfc/mfc_cal.h b/drivers/media/platform/exynos/mfc/mfc_cal.h deleted file mode 100644 index 7bed92ca4370..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_cal.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_cmd.c b/drivers/media/platform/exynos/mfc/mfc_cmd.c index 87dad6691230..bbbb4fb5bf4f 100644 --- a/drivers/media/platform/exynos/mfc/mfc_cmd.c +++ b/drivers/media/platform/exynos/mfc/mfc_cmd.c @@ -14,8 +14,8 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_common.h b/drivers/media/platform/exynos/mfc/mfc_common.h index c45acb36903e..33481ca6aa86 100644 --- a/drivers/media/platform/exynos/mfc/mfc_common.h +++ b/drivers/media/platform/exynos/mfc/mfc_common.h @@ -22,7 +22,7 @@ #include #include -#include "mfc_regs_v10.h" +#include "mfc_regs.h" #include "mfc_macros.h" #include "mfc_debug.h" #include "exynos_mfc_media.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_ctrl.c b/drivers/media/platform/exynos/mfc/mfc_ctrl.c index cef16fa01ba0..9da4eb37d58e 100644 --- a/drivers/media/platform/exynos/mfc/mfc_ctrl.c +++ b/drivers/media/platform/exynos/mfc/mfc_ctrl.c @@ -18,8 +18,8 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_dec.c b/drivers/media/platform/exynos/mfc/mfc_dec.c deleted file mode 100644 index 9c004a2a6b41..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_dec.c +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * 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; -} diff --git a/drivers/media/platform/exynos/mfc/mfc_dec.h b/drivers/media/platform/exynos/mfc/mfc_dec.h deleted file mode 100644 index b9f9081ab422..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_dec.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_ctrl.c b/drivers/media/platform/exynos/mfc/mfc_dec_ctrl.c new file mode 100644 index 000000000000..6cbedd71880b --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_dec_ctrl.c @@ -0,0 +1,896 @@ +/* + * 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, +}; diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_ops.c b/drivers/media/platform/exynos/mfc/mfc_dec_ops.c deleted file mode 100644 index cbc0bfc2cfa0..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_dec_ops.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - * 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, -}; diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c new file mode 100644 index 000000000000..27dc71142f67 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c @@ -0,0 +1,1279 @@ +/* + * 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; +} diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.h b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.h new file mode 100644 index 000000000000..2617461d1a16 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.h @@ -0,0 +1,20 @@ +/* + * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c new file mode 100644 index 000000000000..a07446e16b59 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c @@ -0,0 +1,633 @@ +/* + * 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, +}; diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c b/drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c deleted file mode 100644 index a07446e16b59..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * 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, -}; diff --git a/drivers/media/platform/exynos/mfc/mfc_enc.c b/drivers/media/platform/exynos/mfc/mfc_enc.c deleted file mode 100644 index ab5249b9f3ba..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_enc.c +++ /dev/null @@ -1,2061 +0,0 @@ -/* - * 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; -} diff --git a/drivers/media/platform/exynos/mfc/mfc_enc.h b/drivers/media/platform/exynos/mfc/mfc_enc.h deleted file mode 100644 index f2092faf966c..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_enc.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_ctrl.c b/drivers/media/platform/exynos/mfc/mfc_enc_ctrl.c new file mode 100644 index 000000000000..eb6269a046ec --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_enc_ctrl.c @@ -0,0 +1,1622 @@ +/* + * 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, +}; diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_ops.c b/drivers/media/platform/exynos/mfc/mfc_enc_ops.c deleted file mode 100644 index 824fe5330651..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_enc_ops.c +++ /dev/null @@ -1,1622 +0,0 @@ -/* - * 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, -}; diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_param.c b/drivers/media/platform/exynos/mfc/mfc_enc_param.c index aaea80deb188..d037643a5b53 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_param.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_param.c @@ -12,7 +12,7 @@ #include "mfc_enc_param.h" -#include "mfc_reg.h" +#include "mfc_reg_api.h" /* Definition */ #define FRAME_DELTA_DEFAULT 1 diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c new file mode 100644 index 000000000000..d491a2379eb6 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c @@ -0,0 +1,2061 @@ +/* + * 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; +} diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.h b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.h new file mode 100644 index 000000000000..24a24dd277c0 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.h @@ -0,0 +1,20 @@ +/* + * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c new file mode 100644 index 000000000000..6d9ef8f24ca9 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c @@ -0,0 +1,478 @@ +/* + * 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, +}; diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c b/drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c deleted file mode 100644 index 6d9ef8f24ca9..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * 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, -}; diff --git a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c new file mode 100644 index 000000000000..40260069d3ff --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.c @@ -0,0 +1,101 @@ +/* + * 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 + +#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; +} diff --git a/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h new file mode 100644 index 000000000000..9d1245ddf684 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h @@ -0,0 +1,111 @@ +/* + * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_hwlock.c b/drivers/media/platform/exynos/mfc/mfc_hwlock.c index 0821b1834bab..f67ba97070c0 100644 --- a/drivers/media/platform/exynos/mfc/mfc_hwlock.c +++ b/drivers/media/platform/exynos/mfc/mfc_hwlock.c @@ -20,8 +20,8 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_inst.c b/drivers/media/platform/exynos/mfc/mfc_inst.c index 8e130879aba3..2e37a49f7f3f 100644 --- a/drivers/media/platform/exynos/mfc/mfc_inst.c +++ b/drivers/media/platform/exynos/mfc/mfc_inst.c @@ -14,9 +14,9 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_irq.c b/drivers/media/platform/exynos/mfc/mfc_irq.c deleted file mode 100644 index 680ce74ef09a..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_irq.c +++ /dev/null @@ -1,1564 +0,0 @@ -/* - * 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; -} diff --git a/drivers/media/platform/exynos/mfc/mfc_irq.h b/drivers/media/platform/exynos/mfc/mfc_irq.h deleted file mode 100644 index 872596a2653c..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_irq.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 - -#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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.c b/drivers/media/platform/exynos/mfc/mfc_isr.c new file mode 100644 index 000000000000..d940839dcc13 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_isr.c @@ -0,0 +1,1564 @@ +/* + * 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; +} diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.h b/drivers/media/platform/exynos/mfc/mfc_isr.h new file mode 100644 index 000000000000..e9767e70b430 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_isr.h @@ -0,0 +1,32 @@ +/* + * 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 + +#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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_mmcache.c b/drivers/media/platform/exynos/mfc/mfc_mmcache.c index 3587d8bc27c7..624478d11a45 100644 --- a/drivers/media/platform/exynos/mfc/mfc_mmcache.c +++ b/drivers/media/platform/exynos/mfc/mfc_mmcache.c @@ -12,7 +12,7 @@ #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, diff --git a/drivers/media/platform/exynos/mfc/mfc_nal_q.c b/drivers/media/platform/exynos/mfc/mfc_nal_q.c index 870620e10792..ac533e3fdc2f 100644 --- a/drivers/media/platform/exynos/mfc/mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/mfc_nal_q.c @@ -15,8 +15,8 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_opr.c b/drivers/media/platform/exynos/mfc/mfc_opr.c index 776e67363375..34bd0be0ff4e 100644 --- a/drivers/media/platform/exynos/mfc/mfc_opr.c +++ b/drivers/media/platform/exynos/mfc/mfc_opr.c @@ -13,7 +13,7 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_otf.c b/drivers/media/platform/exynos/mfc/mfc_otf.c index aa95f5133a84..59b04c43adce 100644 --- a/drivers/media/platform/exynos/mfc/mfc_otf.c +++ b/drivers/media/platform/exynos/mfc/mfc_otf.c @@ -26,7 +26,7 @@ #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" diff --git a/drivers/media/platform/exynos/mfc/mfc_perf_measure.h b/drivers/media/platform/exynos/mfc/mfc_perf_measure.h index 9b74b773ce3e..dc3a41b99c0e 100644 --- a/drivers/media/platform/exynos/mfc/mfc_perf_measure.h +++ b/drivers/media/platform/exynos/mfc/mfc_perf_measure.h @@ -15,7 +15,7 @@ #include -#include "mfc_reg.h" +#include "mfc_reg_api.h" void mfc_perf_register(struct mfc_dev *dev); void __mfc_measure_init(void); diff --git a/drivers/media/platform/exynos/mfc/mfc_pm.c b/drivers/media/platform/exynos/mfc/mfc_pm.c index 0f7bfd26b312..efa109dc7583 100644 --- a/drivers/media/platform/exynos/mfc/mfc_pm.c +++ b/drivers/media/platform/exynos/mfc/mfc_pm.c @@ -16,8 +16,8 @@ #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) { diff --git a/drivers/media/platform/exynos/mfc/mfc_reg.c b/drivers/media/platform/exynos/mfc/mfc_reg.c deleted file mode 100644 index 772af91d4ada..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_reg.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * 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 - -#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); -} diff --git a/drivers/media/platform/exynos/mfc/mfc_reg.h b/drivers/media/platform/exynos/mfc/mfc_reg.h deleted file mode 100644 index 757b3d11e00e..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_reg.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_reg_api.c b/drivers/media/platform/exynos/mfc/mfc_reg_api.c new file mode 100644 index 000000000000..469a7fc39221 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_reg_api.c @@ -0,0 +1,547 @@ +/* + * 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 + +#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); +} diff --git a/drivers/media/platform/exynos/mfc/mfc_reg_api.h b/drivers/media/platform/exynos/mfc/mfc_reg_api.h new file mode 100644 index 000000000000..4a0110e1bda8 --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_reg_api.h @@ -0,0 +1,271 @@ +/* + * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_regs.h b/drivers/media/platform/exynos/mfc/mfc_regs.h new file mode 100644 index 000000000000..ee569f44849a --- /dev/null +++ b/drivers/media/platform/exynos/mfc/mfc_regs.h @@ -0,0 +1,743 @@ +/* + * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_regs_v10.h b/drivers/media/platform/exynos/mfc/mfc_regs_v10.h deleted file mode 100644 index e50d495ad0b6..000000000000 --- a/drivers/media/platform/exynos/mfc/mfc_regs_v10.h +++ /dev/null @@ -1,743 +0,0 @@ -/* - * 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 */ diff --git a/drivers/media/platform/exynos/mfc/mfc_sync.c b/drivers/media/platform/exynos/mfc/mfc_sync.c index 0a7669b053b6..b3a85415e45f 100644 --- a/drivers/media/platform/exynos/mfc/mfc_sync.c +++ b/drivers/media/platform/exynos/mfc/mfc_sync.c @@ -12,7 +12,7 @@ #include "mfc_sync.h" -#include "mfc_cal.h" +#include "mfc_hw_reg_api.h" #include "mfc_perf_measure.h" #include "mfc_queue.h" diff --git a/drivers/media/platform/exynos/mfc/mfc_watchdog.c b/drivers/media/platform/exynos/mfc/mfc_watchdog.c index 0a10cfbf4d18..64a3d8e43528 100644 --- a/drivers/media/platform/exynos/mfc/mfc_watchdog.c +++ b/drivers/media/platform/exynos/mfc/mfc_watchdog.c @@ -19,8 +19,8 @@ #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"