@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
rk-mpp-service-objs := mpp_service.o
rk-mpp-device-objs := mpp_dev_common.o
-rk-mpp-vdpu2-objs := mpp_dev_vdpu2.o
+rk-mpp-vdpu2-objs := mpp_dev_vdpu2.o vdpu2/mpeg2.o
obj-$(CONFIG_ROCKCHIP_MPP_SERVICE) += rk-mpp-service.o
obj-$(CONFIG_ROCKCHIP_MPP_DEVICE) += rk-mpp-device.o
@@ -24,61 +24,18 @@
#include <linux/uaccess.h>
#include <soc/rockchip/pm_domains.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+
#include "mpp_debug.h"
#include "mpp_dev_common.h"
+#include "vdpu2/hal.h"
#define RKVDPU2_DRIVER_NAME "mpp_vdpu2"
#define RKVDPU2_NODE_NAME "vpu-service"
-/* The maximum registers number of all the version */
-#define ROCKCHIP_VDPU2_REG_NUM 159
-
-/* The first register of the decoder is Reg50(0x000c8) */
-#define RKVDPU2_REG_DEC_CTRL 0x0c8
-#define RKVDPU2_REG_DEC_CTRL_INDEX (50)
-
-#define RKVDPU2_REG_SYS_CTRL 0x0d4
-#define RKVDPU2_REG_SYS_CTRL_INDEX (53)
-#define RKVDPU2_GET_FORMAT(x) ((x) & 0xf)
-#define RKVDPU2_FMT_H264D 0
-#define RKVDPU2_FMT_MPEG4D 1
-#define RKVDPU2_FMT_H263D 2
-#define RKVDPU2_FMT_JPEGD 3
-#define RKVDPU2_FMT_VC1D 4
-#define RKVDPU2_FMT_MPEG2D 5
-#define RKVDPU2_FMT_MPEG1D 6
-#define RKVDPU2_FMT_VP6D 7
-#define RKVDPU2_FMT_RESERVED 8
-#define RKVDPU2_FMT_VP7D 9
-#define RKVDPU2_FMT_VP8D 10
-#define RKVDPU2_FMT_AVSD 11
-
-#define RKVDPU2_REG_DEC_INT_EN 0x0dc
-#define RKVDPU2_REG_DEC_INT_EN_INDEX (55)
-#define RKVDPU2_INT_TIMEOUT BIT(13)
-#define RKVDPU2_INT_STRM_ERROR BIT(12)
-#define RKVDPU2_INT_SLICE BIT(9)
-#define RKVDPU2_INT_ASO_ERROR BIT(8)
-#define RKVDPU2_INT_BUF_EMPTY BIT(6)
-#define RKVDPU2_INT_BUS_ERROR BIT(5)
-#define RKVDPU2_DEC_INT BIT(4)
-#define RKVDPU2_DEC_IRQ_DIS BIT(1)
-#define RKVDPU2_DEC_INT_RAW BIT(0)
-
-#define RKVDPU2_REG_DEC_DEV_CTRL 0x0e4
-#define RKVDPU2_REG_DEC_DEV_CTRL_INDEX (57)
-#define RKVDPU2_DEC_CLOCK_GATE_EN BIT(4)
-#define RKVDPU2_DEC_START BIT(0)
-
-#define RKVDPU2_REG59 0x0ec
-#define RKVDPU2_REG59_INDEX (59)
-
-#define RKVDPU2_REG_DIR_MV_BASE 0x0f8
-#define RKVDPU2_REG_DIR_MV_BASE_INDEX (62)
-
-#define RKVDPU2_REG_STREAM_RLC_BASE 0x100
-#define RKVDPU2_REG_STREAM_RLC_BASE_INDEX (64)
-
#define to_rkvdpu_task(ctx) \
container_of(ctx, struct rkvdpu_task, mpp_task)
#define to_rkvdpu_dev(dev) \
@@ -102,184 +59,389 @@ struct rkvdpu_task {
u32 reg[ROCKCHIP_VDPU2_REG_NUM];
u32 idx;
- struct extra_info_for_iommu ext_inf;
u32 strm_base;
u32 irq_status;
};
-/*
- * file handle translate information
- */
-static const char trans_tbl_default[] = {
- 61, 62, 63, 64, 131, 134, 135, 148
+static struct rockchip_mpp_control vdpu_controls[] = {
+ {
+ .codec = V4L2_PIX_FMT_MPEG2_SLICE,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+ .elem_size = sizeof(struct v4l2_ctrl_mpeg2_slice_params),
+ },
+ {
+ .codec = V4L2_PIX_FMT_MPEG2_SLICE,
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+ .elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization),
+ },
};
-static const char trans_tbl_jpegd[] = {
- 21, 22, 61, 63, 64, 131
+static struct v4l2_pix_format_mplane fmt_out_templ[] = {
+ {
+ .pixelformat = V4L2_PIX_FMT_MPEG2_SLICE,
+ },
+ {.pixelformat = 0},
};
-static const char trans_tbl_h264d[] = {
- 61, 63, 64, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
- 98, 99
+static struct v4l2_pix_format_mplane fmt_cap_templ[] = {
+ {
+ .pixelformat = V4L2_PIX_FMT_NV12M,
+ },
+ {.pixelformat = 0},
};
-static const char trans_tbl_vc1d[] = {
- 62, 63, 64, 131, 134, 135, 145, 148
+static const struct mpp_dev_variant rkvdpu_v2_data = {
+ /* Exclude the register of the Performance counter */
+ .reg_len = 159,
+ .node_name = RKVDPU2_NODE_NAME,
+ .vfd_func = MEDIA_ENT_F_PROC_VIDEO_DECODER,
};
-static const char trans_tbl_vp6d[] = {
- 61, 63, 64, 131, 136, 145
-};
+static int rkvdpu_open(struct file *filp);
-static const char trans_tbl_vp8d[] = {
- 61, 63, 64, 131, 136, 137, 140, 141, 142, 143, 144, 145, 146, 147, 149
+static const struct v4l2_file_operations rkvdpu_fops = {
+ .open = rkvdpu_open,
+ .release = rockchip_mpp_dev_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
};
-static struct mpp_trans_info trans_rk_vdpu2[] = {
- [RKVDPU2_FMT_H264D] = {
- .count = sizeof(trans_tbl_h264d),
- .table = trans_tbl_h264d,
- },
- [RKVDPU2_FMT_H263D] = {
- .count = sizeof(trans_tbl_default),
- .table = trans_tbl_default,
- },
- [RKVDPU2_FMT_MPEG4D] = {
- .count = sizeof(trans_tbl_default),
- .table = trans_tbl_default,
- },
- [RKVDPU2_FMT_JPEGD] = {
- .count = sizeof(trans_tbl_jpegd),
- .table = trans_tbl_jpegd,
- },
- [RKVDPU2_FMT_VC1D] = {
- .count = sizeof(trans_tbl_vc1d),
- .table = trans_tbl_vc1d,
- },
- [RKVDPU2_FMT_MPEG2D] = {
- .count = sizeof(trans_tbl_default),
- .table = trans_tbl_default,
- },
- [RKVDPU2_FMT_MPEG1D] = {
- .count = sizeof(trans_tbl_default),
- .table = trans_tbl_default,
- },
- [RKVDPU2_FMT_VP6D] = {
- .count = sizeof(trans_tbl_vp6d),
- .table = trans_tbl_vp6d,
- },
- [RKVDPU2_FMT_RESERVED] = {
- .count = 0,
- .table = NULL,
- },
- [RKVDPU2_FMT_VP7D] = {
- .count = sizeof(trans_tbl_default),
- .table = trans_tbl_default,
- },
- [RKVDPU2_FMT_VP8D] = {
- .count = sizeof(trans_tbl_vp8d),
- .table = trans_tbl_vp8d,
- },
- [RKVDPU2_FMT_AVSD] = {
- .count = sizeof(trans_tbl_default),
- .table = trans_tbl_default,
- },
-};
+#if 1
+static struct v4l2_ioctl_ops rkvdpu_ioctl_ops = { 0, };
+#endif
-static const struct mpp_dev_variant rkvdpu_v2_data = {
- /* Exclude the register of the Performance counter */
- .reg_len = 159,
- .trans_info = trans_rk_vdpu2,
- .node_name = RKVDPU2_NODE_NAME,
+static void *rockchip_rkvdpu2_get_drv_data(struct platform_device *pdev);
+
+#if 0
+static int rockchip_mpp_queue_setup(struct vb2_queue *vq,
+ unsigned int *num_buffers,
+ unsigned int *num_planes,
+ unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct mpp_session *session = vb2_get_drv_priv(vq);
+ struct v4l2_pix_format_mplane pixfmt;
+ unsigned int size;
+
+ switch (vq->type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ pixfmt = &session->fmt_out;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pixfmt = &session->fmt_cap;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (*num_planes) {
+ if (*num_planes != pixfmt->num_planes)
+ return -EINVAL;
+ for (i = 0; i < pixfmt->num_planes; ++i)
+ if (sizes[i] < pixfmt->plane_fmt[i].sizeimage)
+ return -EINVAL;
+
+ return 0;
+ }
+
+ *num_planes = pixfmt->num_planes;
+ for (i = 0; i < pixfmt->num_planes; ++i)
+ sizes[i] = pixfmt->plane_fmt[i].sizeimage;
+
+ return 0;
+}
+
+static const struct vb2_ops rkvdpu_queue_ops = {
+ .queue_setup = rockchip_mpp_queue_setup,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ /* TODO */
+ .start_streaming = NULL,
+ .stop_streaming = NULL,
+ .buf_queue = = rockchip_mpp_buf_queue,
+ .buf_request_complete = rockchip_mpp_buf_request_complete,
};
-static void *rockchip_rkvdpu2_get_drv_data(struct platform_device *pdev);
+static int rkvdpu_try_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ struct rockchip_mpp_dev *mpp_dev = video_drvdata(filp);
+ struct mpp_session *session = container_of(filp->private_data,
+ struct mpp_session, fh);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
-static void *rockchip_mpp_rkvdpu_alloc_task(struct mpp_session *session,
- void __user *src, u32 size)
+ return 0;
+}
+
+static int rkvdpu_try_fmt_vid_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
{
- struct rkvdpu_task *task = NULL;
- u32 reg_len;
- u32 extinf_len;
- u32 fmt = 0;
- u32 dwsize = size / sizeof(u32);
- int err = -EFAULT;
+ struct rockchip_mpp_dev *mpp_dev = video_drvdata(filp);
+ struct mpp_session *session = container_of(filp->private_data,
+ struct mpp_session, fh);
+ struct v4l2_pix_format *pix = &f->fmt.pix;
- mpp_debug_enter();
+ return 0;
+}
+#endif
- task = kzalloc(sizeof(*task), GFP_KERNEL);
- if (!task)
- return NULL;
+static int rkvdpu_s_fmt_vid_out_mplane(struct file *filp, void *priv,
+ struct v4l2_format *f)
+{
+ struct mpp_session *session = container_of(filp->private_data,
+ struct mpp_session, fh);
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+ struct vb2_queue *vq;
+ int sizes = 0;
+ int i;
+
+ /* TODO: We can change width and height at streaming on */
+ vq = v4l2_m2m_get_vq(session->fh.m2m_ctx, f->type);
+ if (vb2_is_streaming(vq))
+ return -EBUSY;
+
+#if 0
+ ret = rkvdpu_try_fmt_out(filp, priv, f);
+ if (ret)
+ return ret;
+#endif
+ for (i = 0; i < pix_mp->num_planes; i++) {
+ sizes += pix_mp->plane_fmt[i].sizeimage;
+ }
+ /* strm_len is 24 bits */
+ if (sizes >= SZ_16M)
+ return -EINVAL;
- mpp_dev_task_init(session, &task->mpp_task);
+ if (!pix_mp->num_planes)
+ pix_mp->num_planes = 1;
+
+ session->fmt_out = *pix_mp;
+
+ /* Copy the pixel format information from OUTPUT to CAPUTRE */
+ session->fmt_cap.pixelformat = V4L2_PIX_FMT_NV12M;
+ session->fmt_cap.width = pix_mp->width;
+ session->fmt_cap.height = pix_mp->height;
+ session->fmt_cap.colorspace = pix_mp->colorspace;
+ session->fmt_cap.ycbcr_enc = pix_mp->ycbcr_enc;
+ session->fmt_cap.xfer_func = pix_mp->xfer_func;
+ session->fmt_cap.quantization = pix_mp->quantization;
+
+ return 0;
+}
+
+static int rkvdpu_s_fmt_vid_cap_mplane(struct file *filp, void *priv,
+ struct v4l2_format *f)
+{
+ struct mpp_session *session = container_of(filp->private_data,
+ struct mpp_session, fh);
+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+ struct vb2_queue *vq;
+
+ vq = v4l2_m2m_get_vq(session->fh.m2m_ctx, f->type);
+ if (vb2_is_streaming(vq))
+ return -EBUSY;
+
+#if 0
+ ret = rkvdpu_try_fmt_cap(filp, priv, f);
+ if (ret)
+ return ret;
+#endif
+ switch (pix_mp->pixelformat) {
+ case V4L2_PIX_FMT_NV12M:
+ pix_mp->plane_fmt[0].bytesperline = ALIGN(pix_mp->width, 16);
+ pix_mp->plane_fmt[1].bytesperline = ALIGN(pix_mp->width, 16);
+ pix_mp->plane_fmt[0].sizeimage = ALIGN(pix_mp->width, 16) *
+ ALIGN(pix_mp->height, 16);
+ /* Additional space for motion vector */
+ pix_mp->plane_fmt[1].sizeimage = ALIGN(pix_mp->width, 16) *
+ ALIGN(pix_mp->height, 16);
+ pix_mp->num_planes = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ session->fmt_cap = *pix_mp;
+
+ return 0;
+}
+
+#if 0
+static int rkvdpu_queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
+{
+ struct mpp_session *session = priv;
+ int ret;
- reg_len = dwsize > ROCKCHIP_VDPU2_REG_NUM ?
- ROCKCHIP_VDPU2_REG_NUM : dwsize;
- extinf_len = dwsize > reg_len ? (dwsize - reg_len) * 4 : 0;
+ rockchip_mpp_queue_init(priv, src_vq, dst_vq);
- if (copy_from_user(task->reg, src, reg_len * 4)) {
- mpp_err("error: copy_from_user failed in reg_init\n");
- err = -EFAULT;
+ src_vq->ops = rkvdpu_queue_ops;
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+ return ret;
+
+ dst_vq->ops = rkvdpu_queue_ops;
+ return vb2_queue_init(dst_vq);
+}
+
+static int mpp_dev_open(struct file *filp)
+{
+ struct rockchip_mpp_dev *mpp_dev = video_drvdata(filp);
+ struct video_device *vdev = video_devdata(filp);
+ struct mpp_session *session = NULL;
+ int error = 0;
+
+ mpp_debug_enter();
+
+ session = rockchip_alloc_session(mpp_dev);
+ if (IS_ERR(session))
+ return PTR_ERR(session);
+
+ session->fh.m2m_ctx = v4l2_m2m_ctx_init(mpp_dev->m2m_dev, session,
+ rockchip_mpp_queue_init);
+ if (IS_ERR(session->fh.m2m_ctx)) {
+ error = PTR_ERR(session->fb.m2m_ctx);
goto fail;
}
+ v4l2_fh_init(&session->fh, vdev);
+ filp->private_data = &session->fh;
+ v4l2_fh_add(&session->fh);
- fmt = RKVDPU2_GET_FORMAT(task->reg[RKVDPU2_REG_SYS_CTRL_INDEX]);
- if (extinf_len > 0) {
- if (likely(fmt == RKVDPU2_FMT_JPEGD)) {
- err = copy_from_user(&task->ext_inf,
- (u8 *)src + size
- - JPEG_IOC_EXTRA_SIZE,
- JPEG_IOC_EXTRA_SIZE);
- } else {
- u32 ext_cpy = min_t(size_t, extinf_len,
- sizeof(task->ext_inf));
- err = copy_from_user(&task->ext_inf,
- (u32 *)src + reg_len, ext_cpy);
- }
+ /* TODO: setup default formats */
+
+ /* TODO: install v4l2 ctrl */
+ if (error) {
+ dev_err(mpp_dev->dev, "Failed to set up controls\n");
+ goto err_fh;
+ }
+
+ session->fb.ctrl_handler = session->ctrl_handler;
+
+ mpp_dev_power_on(mpp);
+ mpp_debug_leave();
- if (err) {
- mpp_err("copy_from_user failed when extra info\n");
- err = -EFAULT;
+ return 0;
+
+err_fh:
+ v4l2_fh_del(&session->fh);
+ v4l2_fh_exit(&session->fh);
+fail:
+ kfree(session);
+ return error;
+}
+#endif
+
+static int vdpu_setup_ctrls(struct rockchip_mpp_dev *mpp_dev,
+ struct mpp_session *session)
+{
+ struct v4l2_ctrl_handler *hdl = &session->ctrl_handler;
+ struct v4l2_ctrl *ctrl;
+ unsigned int num_ctrls = ARRAY_SIZE(vdpu_controls);
+ unsigned int i;
+
+ v4l2_ctrl_handler_init(hdl, num_ctrls);
+ if (hdl->error) {
+ v4l2_err(&mpp_dev->v4l2_dev,
+ "Failed to initialize control handler\n");
+ return hdl->error;
+ }
+#if 0
+ ctrls_size = sizeof(ctrl) * num_ctrls + 1;
+ session->ctrls = kzalloc(ctrls_size, GFP_KERNEL);
+#endif
+
+ for (i = 0; i < num_ctrls; i++) {
+ struct v4l2_ctrl_config cfg = { };
+
+ cfg.id = vdpu_controls[i].id;
+ cfg.elem_size = vdpu_controls[i].elem_size;
+
+ ctrl = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+ if (hdl->error) {
+ v4l2_err(&mpp_dev->v4l2_dev,
+ "Failed to create new custom %d control\n",
+ cfg.id);
goto fail;
}
+#if 0
+ session->ctrls[i] = ctrl;
+#endif
}
- err = mpp_reg_address_translate(session->mpp, &task->mpp_task, fmt,
- task->reg);
- if (err) {
- mpp_err("error: translate reg address failed.\n");
+ session->fh.ctrl_handler = hdl;
+ v4l2_ctrl_handler_setup(hdl);
- if (unlikely(debug & DEBUG_DUMP_ERR_REG))
- mpp_debug_dump_reg_mem(task->reg,
- ROCKCHIP_VDPU2_REG_NUM);
- goto fail;
+ return 0;
+fail:
+ v4l2_ctrl_handler_free(hdl);
+#if 0
+ kfree(session->ctrls);
+#endif
+ return hdl->error;
+}
+
+static int rkvdpu_open(struct file *filp)
+{
+ struct rockchip_mpp_dev *mpp_dev = video_drvdata(filp);
+ struct video_device *vdev = video_devdata(filp);
+ struct mpp_session *session = NULL;
+ /* TODO: install ctrl based on register report */
+ int error = 0;
+
+ mpp_debug_enter();
+
+ session = rockchip_mpp_alloc_session(mpp_dev, vdev);
+ if (IS_ERR_OR_NULL(session))
+ return PTR_ERR(session);
+
+ error = vdpu_setup_ctrls(mpp_dev, session);
+ if (error) {
+ kfree(session);
+ return error;
}
- if (likely(fmt == RKVDPU2_FMT_H264D)) {
- struct mpp_mem_region *mem_region = NULL;
- dma_addr_t iova = 0;
- u32 offset = task->reg[RKVDPU2_REG_DIR_MV_BASE_INDEX];
- int fd = task->reg[RKVDPU2_REG_DIR_MV_BASE_INDEX] & 0x3ff;
+ filp->private_data = &session->fh;
- offset = offset >> 10 << 4;
- mem_region = mpp_dev_task_attach_fd(&task->mpp_task, fd);
- if (IS_ERR(mem_region)) {
- err = PTR_ERR(mem_region);
- goto fail;
- }
+ mpp_debug_leave();
+ return 0;
+}
+
+static void *rockchip_mpp_rkvdpu_alloc_task(struct mpp_session *session,
+ void __user * src, u32 size)
+{
+ struct rkvdpu_task *task = NULL;
+ struct vb2_v4l2_buffer *src_buf;
+ u32 fmt = 0;
+ int err = -EFAULT;
- iova = mem_region->iova;
- mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n",
- RKVDPU2_REG_DIR_MV_BASE_INDEX, fd, &iova, offset);
- task->reg[RKVDPU2_REG_DIR_MV_BASE_INDEX] = iova + offset;
+ mpp_debug_enter();
+
+ task = kzalloc(sizeof(*task), GFP_KERNEL);
+ if (!task)
+ return NULL;
+
+ mpp_dev_task_init(session, &task->mpp_task);
+
+ src_buf = v4l2_m2m_next_src_buf(session->fh.m2m_ctx);
+ v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
+ &session->ctrl_handler);
+
+ fmt = session->fmt_out.pixelformat;
+ switch (fmt) {
+ case V4L2_PIX_FMT_MPEG2_SLICE:
+ err = rkvdpu_mpeg2_gen_reg(session, task->reg, src_buf);
+ break;
+ default:
+ goto fail;
}
- task->strm_base = task->reg[RKVDPU2_REG_STREAM_RLC_BASE_INDEX];
+ if (err)
+ goto fail;
- mpp_debug(DEBUG_SET_REG, "extra info cnt %u, magic %08x",
- task->ext_inf.cnt, task->ext_inf.magic);
- mpp_translate_extra_info(&task->mpp_task, &task->ext_inf, task->reg);
+ v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
+ &session->ctrl_handler);
mpp_debug_leave();
@@ -289,15 +451,17 @@ static void *rockchip_mpp_rkvdpu_alloc_task(struct mpp_session *session,
if (unlikely(debug & DEBUG_DUMP_ERR_REG))
mpp_debug_dump_reg_mem(task->reg, ROCKCHIP_VDPU2_REG_NUM);
- mpp_dev_task_finalize(session, &task->mpp_task);
kfree(task);
return ERR_PTR(err);
}
static int rockchip_mpp_rkvdpu_prepare(struct rockchip_mpp_dev *mpp_dev,
- struct mpp_task *task)
+ struct mpp_task *mpp_task)
{
- return -EINVAL;
+ struct rkvdpu_task *task = container_of(mpp_task, struct rkvdpu_task,
+ mpp_task);
+
+ return rkvdpu_mpeg2_prepare_buf(mpp_task->session, task->reg);
}
static int rockchip_mpp_rkvdpu_run(struct rockchip_mpp_dev *mpp_dev,
@@ -355,17 +519,21 @@ static int rockchip_mpp_rkvdpu_finish(struct rockchip_mpp_dev *mpp_dev,
static int rockchip_mpp_rkvdpu_result(struct rockchip_mpp_dev *mpp_dev,
struct mpp_task *mpp_task,
- u32 __user *dst, u32 size)
+ u32 __user * dst, u32 size)
{
struct rkvdpu_task *task = to_rkvdpu_task(mpp_task);
+ u32 err_mask;
- /* FIXME may overflow the kernel */
- if (copy_to_user(dst, task->reg, size)) {
- mpp_err("copy_to_user failed\n");
- return -EIO;
- }
+ err_mask = RKVDPU2_INT_TIMEOUT
+ | RKVDPU2_INT_STRM_ERROR
+ | RKVDPU2_INT_ASO_ERROR
+ | RKVDPU2_INT_BUF_EMPTY
+ | RKVDPU2_INT_BUS_ERROR;
- return 0;
+ if (err_mask & task->irq_status)
+ return VB2_BUF_STATE_ERROR;
+
+ return VB2_BUF_STATE_DONE;
}
static int rockchip_mpp_rkvdpu_free_task(struct mpp_session *session,
@@ -406,14 +574,13 @@ static irqreturn_t mpp_rkvdpu_isr(int irq, void *dev_id)
mpp_task = &task->mpp_task;
mpp_debug_time_diff(mpp_task);
task->irq_status = irq_status;
- mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n",
- task->irq_status);
+ mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n", task->irq_status);
err_mask = RKVDPU2_INT_TIMEOUT
- | RKVDPU2_INT_STRM_ERROR
- | RKVDPU2_INT_ASO_ERROR
- | RKVDPU2_INT_BUF_EMPTY
- | RKVDPU2_INT_BUS_ERROR;
+ | RKVDPU2_INT_STRM_ERROR
+ | RKVDPU2_INT_ASO_ERROR
+ | RKVDPU2_INT_BUF_EMPTY
+ | RKVDPU2_INT_BUS_ERROR;
if (err_mask & task->irq_status)
atomic_set(&mpp_dev->reset_request, 1);
@@ -504,10 +671,19 @@ static int rockchip_mpp_rkvdpu_probe(struct platform_device *pdev)
rockchip_mpp_rkvdpu_assign_reset(dec_dev);
- ret = mpp_dev_register_node(mpp_dev, mpp_dev->variant->node_name, NULL);
+ rkvdpu_ioctl_ops = mpp_ioctl_ops_templ;
+ rkvdpu_ioctl_ops.vidioc_s_fmt_vid_out_mplane =
+ rkvdpu_s_fmt_vid_out_mplane;
+ rkvdpu_ioctl_ops.vidioc_s_fmt_vid_cap_mplane =
+ rkvdpu_s_fmt_vid_cap_mplane;
+
+ ret = mpp_dev_register_node(mpp_dev, mpp_dev->variant->node_name,
+ &rkvdpu_fops, &rkvdpu_ioctl_ops);
if (ret)
dev_err(dev, "register char device failed: %d\n", ret);
+ memcpy(mpp_dev->fmt_out, fmt_out_templ, sizeof(fmt_out_templ));
+ memcpy(mpp_dev->fmt_cap, fmt_cap_templ, sizeof(fmt_cap_templ));
dev_info(dev, "probing finish\n");
platform_set_drvdata(pdev, dec_dev);
@@ -525,7 +701,7 @@ static int rockchip_mpp_rkvdpu_remove(struct platform_device *pdev)
}
static const struct of_device_id mpp_rkvdpu2_dt_match[] = {
- { .compatible = "rockchip,vpu-decoder-v2", .data = &rkvdpu_v2_data},
+ {.compatible = "rockchip,vpu-decoder-v2",.data = &rkvdpu_v2_data},
{},
};
@@ -547,9 +723,9 @@ static struct platform_driver rockchip_rkvdpu2_driver = {
.probe = rockchip_mpp_rkvdpu_probe,
.remove = rockchip_mpp_rkvdpu_remove,
.driver = {
- .name = RKVDPU2_DRIVER_NAME,
- .of_match_table = of_match_ptr(mpp_rkvdpu2_dt_match),
- },
+ .name = RKVDPU2_DRIVER_NAME,
+ .of_match_table = of_match_ptr(mpp_rkvdpu2_dt_match),
+ },
};
static int __init mpp_dev_rkvdpu2_init(void)
new file mode 100644
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Randy Li, <ayaka@soulik.info>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VDPU2_HAL_H_
+#define _VDPU2_HAL_H_
+
+#include <linux/types.h>
+
+/* The maximum registers number of all the version */
+#define ROCKCHIP_VDPU2_REG_NUM 159
+
+/* The first register of the decoder is Reg50(0x000c8) */
+#define RKVDPU2_REG_DEC_CTRL 0x0c8
+#define RKVDPU2_REG_DEC_CTRL_INDEX (50)
+
+#define RKVDPU2_REG_DEC_INT_EN 0x0dc
+#define RKVDPU2_REG_DEC_INT_EN_INDEX (55)
+#define RKVDPU2_INT_TIMEOUT BIT(13)
+#define RKVDPU2_INT_STRM_ERROR BIT(12)
+#define RKVDPU2_INT_SLICE BIT(9)
+#define RKVDPU2_INT_ASO_ERROR BIT(8)
+#define RKVDPU2_INT_BUF_EMPTY BIT(6)
+#define RKVDPU2_INT_BUS_ERROR BIT(5)
+#define RKVDPU2_DEC_INT BIT(4)
+#define RKVDPU2_DEC_IRQ_DIS BIT(1)
+#define RKVDPU2_DEC_INT_RAW BIT(0)
+
+#define RKVDPU2_REG_DEC_DEV_CTRL 0x0e4
+#define RKVDPU2_REG_DEC_DEV_CTRL_INDEX (57)
+#define RKVDPU2_DEC_CLOCK_GATE_EN BIT(4)
+#define RKVDPU2_DEC_START BIT(0)
+
+#define RKVDPU2_REG59 0x0ec
+#define RKVDPU2_REG59_INDEX (59)
+
+int rkvdpu_mpeg2_gen_reg(struct mpp_session *session, void *regs,
+ struct vb2_v4l2_buffer *src_buf);
+int rkvdpu_mpeg2_prepare_buf(struct mpp_session *session, void *regs);
+
+#endif
new file mode 100644
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Randy Li, <ayaka@soulik.info>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "mpp_dev_common.h"
+#include "hal.h"
+#include "regs.h"
+
+#define DEC_LITTLE_ENDIAN (1)
+
+static void init_hw_cfg(struct vdpu2_regs *p_regs)
+{
+ p_regs->sw54.dec_strm_wordsp = 1;
+ p_regs->sw54.dec_strendian_e = DEC_LITTLE_ENDIAN;
+ p_regs->sw54.dec_in_wordsp = 1;
+ p_regs->sw54.dec_out_wordsp = 1;
+ p_regs->sw54.dec_in_endian = DEC_LITTLE_ENDIAN; //change
+ p_regs->sw54.dec_out_endian = DEC_LITTLE_ENDIAN;
+ p_regs->sw57.dec_timeout = 1;
+
+ p_regs->sw57.dec_clk_gate_e = 1;
+
+ p_regs->sw50.tiled_mode_msb = 0;
+ p_regs->sw56.dec_max_burst = 16;
+ p_regs->sw50.dec_scmd_dis = 0;
+ p_regs->sw50.dec_adv_pre_dis = 0;
+ p_regs->sw52.apf_threshold = 8;
+
+ p_regs->sw50.dec_latency = 0;
+ p_regs->sw56.dec_data_disc_e = 0;
+
+ p_regs->sw55.dec_irq = 0;
+ p_regs->sw56.dec_axi_rd_id = 0;
+ p_regs->sw56.dec_axi_wr_id = 0;
+
+ /* default for MPEG-2 */
+ p_regs->sw136.mv_accuracy_fwd = 1;
+ p_regs->sw136.mv_accuracy_bwd = 1;
+}
+
+int rkvdpu_mpeg2_gen_reg(struct mpp_session *session, void *regs,
+ struct vb2_v4l2_buffer *src_buf)
+{
+ const struct v4l2_ctrl_mpeg2_slice_params *params;
+ const struct v4l2_ctrl_mpeg2_quantization *quantization;
+ const struct v4l2_mpeg2_sequence *sequence;
+ const struct v4l2_mpeg2_picture *picture;
+ struct sg_table *sgt;
+ struct vdpu2_regs *p_regs = regs;
+
+ params = rockchip_mpp_get_cur_ctrl(session,
+ V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
+ quantization = rockchip_mpp_get_cur_ctrl(session,
+ V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
+
+ if (!params)
+ return -EINVAL;
+
+ sequence = ¶ms->sequence;
+ picture = ¶ms->picture;
+
+ init_hw_cfg(p_regs);
+
+ p_regs->sw120.pic_mb_width = ALIGN(sequence->horizontal_size, 16);
+ p_regs->sw120.pic_mb_height_p = ALIGN(sequence->vertical_size, 16);
+
+ /* PICT_FRAME */
+ if (picture->picture_structure == 3) {
+ p_regs->sw57.pic_fieldmode_e = 0;
+ } else {
+ p_regs->sw57.pic_fieldmode_e = 1;
+ /* PICT_TOP_FIEL */
+ if (picture->picture_structure == 1)
+ p_regs->sw57.pic_topfield_e = 1;
+ }
+
+ switch (picture->picture_coding_type) {
+ case V4L2_MPEG2_PICTURE_CODING_TYPE_P:
+ p_regs->sw57.pic_inter_e = 1;
+ p_regs->sw57.pic_b_e = 0;
+ break;
+ case V4L2_MPEG2_PICTURE_CODING_TYPE_B:
+ p_regs->sw57.pic_b_e = 1;
+ p_regs->sw57.pic_inter_e = 0;
+ break;
+ case V4L2_MPEG2_PICTURE_CODING_TYPE_I:
+ default:
+ p_regs->sw57.pic_inter_e = 0;
+ p_regs->sw57.pic_b_e = 0;
+ break;
+ }
+
+ if (picture->top_field_first)
+ p_regs->sw120.topfieldfirst_e = 1;
+
+ p_regs->sw57.fwd_interlace_e = 0;
+ p_regs->sw57.write_mvs_e = 0;
+
+ p_regs->sw120.alt_scan_e = picture->alternate_scan;
+ p_regs->sw136.alt_scan_flag_e = picture->alternate_scan;
+
+ p_regs->sw122.qscale_type = picture->q_scale_type;
+ p_regs->sw122.intra_dc_prec = picture->intra_dc_precision;
+ p_regs->sw122.con_mv_e = picture->concealment_motion_vectors;
+ p_regs->sw122.intra_vlc_tab = picture->intra_vlc_format;
+ p_regs->sw122.frame_pred_dct = picture->frame_pred_frame_dct;
+ p_regs->sw51.qp_init = 1;
+
+ /* MPEG-2 decoding mode */
+ p_regs->sw53.dec_mode = RKVDPU2_FMT_MPEG2D;
+
+ p_regs->sw136.fcode_fwd_hor = picture->f_code[0][0];
+ p_regs->sw136.fcode_fwd_ver = picture->f_code[0][1];
+ p_regs->sw136.fcode_bwd_hor = picture->f_code[1][0];
+ p_regs->sw136.fcode_bwd_ver = picture->f_code[1][1];
+
+ p_regs->sw57.pic_interlace_e = 1 - sequence->progressive_sequence;
+#if 0
+ /* MPEG-1 decoding mode */
+ p_regs->sw53.sw_dec_mode = 6;
+ p_regs->sw136.fcode_fwd_hor = picture->f_code[0][1];
+ p_regs->sw136.fcode_fwd_ver = picture->f_code[0][1];
+ p_regs->sw136.fcode_bwd_hor = picture->f_code[1][1];
+ p_regs->sw136.fcode_bwd_ver = picture->f_code[1][1];
+ if (picture->f_code[0][0])
+ p_regs->sw136.mv_accuracy_fwd = 0;
+ if (picture->f_code[1][0]
+ p_regs->sw136.mv_accuracy_bwd = 0;
+#endif
+
+ p_regs->sw52.startmb_x = 0;
+ p_regs->sw52.startmb_y = 0;
+ p_regs->sw57.dec_out_dis = 0;
+ p_regs->sw50.filtering_dis = 1;
+
+ sgt = vb2_dma_sg_plane_desc(&src_buf->vb2_buf, 0);
+ p_regs->sw64.rlc_vlc_base = sg_dma_address(sgt->sgl);
+ p_regs->sw122.strm_start_bit = params->data_bit_offset;
+ p_regs->sw51.stream_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
+
+ return 0;
+}
+
+int rkvdpu_mpeg2_prepare_buf(struct mpp_session *session, void *regs)
+{
+ const struct v4l2_ctrl_mpeg2_slice_params *params;
+ const struct v4l2_mpeg2_sequence *sequence;
+ const struct v4l2_mpeg2_picture *picture;
+ struct vb2_v4l2_buffer *dst_buf;
+ dma_addr_t cur_addr, fwd_addr, bwd_addr;
+ struct sg_table *sgt;
+
+ struct vb2_queue *cap_q = &session->fh.m2m_ctx->cap_q_ctx.q;
+ struct vdpu2_regs *p_regs = regs;
+
+ params = rockchip_mpp_get_cur_ctrl(session,
+ V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
+ picture = ¶ms->picture;
+ sequence = ¶ms->sequence;
+
+ dst_buf = v4l2_m2m_next_dst_buf(session->fh.m2m_ctx);
+
+ sgt = vb2_dma_sg_plane_desc(&dst_buf->vb2_buf, 0);
+ cur_addr = fwd_addr = bwd_addr = sg_dma_address(sgt->sgl);
+
+ if (picture->picture_structure == V4L2_FIELD_BOTTOM)
+ cur_addr += ALIGN(sequence->horizontal_size, 16) << 10;
+ p_regs->sw63.dec_out_base = cur_addr;
+
+ fwd_addr = rockchip_mpp_find_addr(cap_q, &dst_buf->vb2_buf,
+ params->forward_ref_ts);
+ bwd_addr = rockchip_mpp_find_addr(cap_q, &dst_buf->vb2_buf,
+ params->backward_ref_ts);
+
+#if 1
+ /* TODO: picture_structure is compatible with FFmpeg */
+ if (picture->picture_structure == 3 ||
+ picture->picture_coding_type == V4L2_MPEG2_PICTURE_CODING_TYPE_B ||
+ (picture->picture_structure == 1 && picture->top_field_first) ||
+ (picture->picture_structure == 2 && !picture->top_field_first)) {
+ p_regs->sw131.refer0_base = fwd_addr >> 2;
+ p_regs->sw148.refer1_base = fwd_addr >> 2;
+
+ } else if (picture->picture_structure == V4L2_FIELD_TOP) {
+ p_regs->sw131.refer0_base = fwd_addr >> 2;
+ p_regs->sw148.refer1_base = cur_addr >> 2;
+
+ } else if (picture->picture_structure == V4L2_FIELD_BOTTOM) {
+ p_regs->sw131.refer0_base = cur_addr >> 2;
+ p_regs->sw148.refer1_base = fwd_addr >> 2;
+ }
+#else
+ if (picture->picture_coding_type == V4L2_MPEG2_PICTURE_CODING_TYPE_B) {
+ p_regs->sw131.refer0_base = fwd_addr >> 2;
+ p_regs->sw148.refer1_base = fwd_addr >> 2;
+ }
+#endif
+
+ /* Always the same buffer for MPEG-2 */
+ p_regs->sw134.refer2_base = bwd_addr >> 2;
+ p_regs->sw135.refer3_base = bwd_addr >> 2;
+
+#if 0
+ //ref & qtable config
+ p_regs->sw61.qtable_base = mpp_buffer_get_fd(ctx->qp_table);
+#endif
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,699 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ * Randy Li, <ayaka@soulik.info>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _VDPU2_REGS_H_
+#define _VDPU2_REGS_H_
+
+#define RKVDPU2_REG_SYS_CTRL 0x0d4
+#define RKVDPU2_REG_SYS_CTRL_INDEX (53)
+#define RKVDPU2_GET_FORMAT(x) ((x) & 0xf)
+#define RKVDPU2_FMT_H264D 0
+#define RKVDPU2_FMT_MPEG4D 1
+#define RKVDPU2_FMT_H263D 2
+#define RKVDPU2_FMT_JPEGD 3
+#define RKVDPU2_FMT_VC1D 4
+#define RKVDPU2_FMT_MPEG2D 5
+#define RKVDPU2_FMT_MPEG1D 6
+#define RKVDPU2_FMT_VP6D 7
+#define RKVDPU2_FMT_RESERVED 8
+#define RKVDPU2_FMT_VP7D 9
+#define RKVDPU2_FMT_VP8D 10
+#define RKVDPU2_FMT_AVSD 11
+
+#define RKVDPU2_REG_DIR_MV_BASE 0x0f8
+#define RKVDPU2_REG_DIR_MV_BASE_INDEX (62)
+
+#define RKVDPU2_REG_STREAM_RLC_BASE 0x100
+#define RKVDPU2_REG_STREAM_RLC_BASE_INDEX (64)
+
+#if 0
+/*
+ * file handle translate information
+ */
+static const char trans_tbl_default[] = {
+ 61, 62, 63, 64, 131, 134, 135, 148
+};
+
+static const char trans_tbl_jpegd[] = {
+ 21, 22, 61, 63, 64, 131
+};
+
+static const char trans_tbl_h264d[] = {
+ 61, 63, 64, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
+ 98, 99
+};
+
+static const char trans_tbl_vc1d[] = {
+ 62, 63, 64, 131, 134, 135, 145, 148
+};
+
+static const char trans_tbl_vp6d[] = {
+ 61, 63, 64, 131, 136, 145
+};
+
+static const char trans_tbl_vp8d[] = {
+ 61, 63, 64, 131, 136, 137, 140, 141, 142, 143, 144, 145, 146, 147, 149
+};
+#endif
+
+struct vdpu2_regs {
+ u32 sw00_49[50];
+
+ struct {
+ u32 tiled_mode_msb:1;
+ u32 dec_latency:6;
+ u32 dec_fixed_quant:1;
+ u32 filtering_dis:1;
+ u32 skip_sel:1;
+ u32 dec_scmd_dis:1;
+ u32 dec_adv_pre_dis:1;
+ u32 tiled_mode_lsb:1;
+ u32 refbuf_thrd:12;
+ u32 refbuf_pid:5;
+ u32 reverse0:2;
+ } sw50;
+
+ struct {
+ u32 stream_len:24;
+ u32 stream_len_ext:1;
+ u32 qp_init:6;
+ u32 reverse0:1;
+ } sw51;
+
+ struct {
+ /* ydim_mbst */
+ u32 startmb_y:8;
+ /* xdim_mbst */
+ u32 startmb_x:9;
+ /* adv_pref_thrd */
+ u32 apf_threshold:14;
+ u32 reverse0:1;
+ } sw52;
+
+ struct {
+ u32 dec_mode:4;
+ u32 reverse0:28;
+ } sw53;
+
+ struct {
+ u32 dec_in_endian:1;
+ u32 dec_out_endian:1;
+ u32 dec_in_wordsp:1;
+ u32 dec_out_wordsp:1;
+ u32 dec_strm_wordsp:1;
+ u32 dec_strendian_e:1;
+ u32 reverse0:26;
+ } sw54;
+
+ struct {
+ u32 dec_irq:1;
+ u32 dec_irq_dis:1;
+ u32 reverse0:2;
+ u32 dec_rdy_sts:1;
+ u32 pp_bus_sts:1;
+ u32 buf_emt_sts:1;
+ u32 reverse1:1;
+ u32 aso_det_sts:1;
+ u32 slice_det_sts:1;
+ u32 bslice_det_sts:1;
+ u32 reverse2:1;
+ u32 error_det_sts:1;
+ u32 timeout_det_sts:1;
+ u32 reverse3:18;
+ } sw55;
+
+ struct {
+ u32 dec_axi_rd_id:8;
+ u32 dec_axi_wr_id:8;
+ u32 dec_max_burst:5;
+ u32 bus_pos_sel:1;
+ u32 dec_data_disc_e:1;
+ u32 axi_sel:1;
+ u32 reverse0:8;
+ } sw56;
+
+ struct {
+ u32 dec_e:1;
+ u32 refbuf2_buf_e:1;
+ u32 dec_out_dis:1;
+ u32 reserved2:1;
+ u32 dec_clk_gate_e:1;
+ u32 dec_timeout_e:1;
+ /* rd_cnt_tab_en */
+ u32 picord_count_e:1;
+ u32 seq_mbaff_e:1;
+ u32 reftopfirst_e:1;
+ u32 ref_topfield_e:1;
+ u32 write_mvs_e:1;
+ u32 sorenson_e:1;
+ u32 fwd_interlace_e:1;
+ u32 pic_topfield_e:1;
+ /* sw_pic_type_sel0 */
+ u32 pic_inter_e:1;
+ u32 pic_b_e:1;
+ u32 pic_fieldmode_e:1;
+ u32 pic_interlace_e:1;
+ u32 pjpeg_e:1;
+ u32 divx3_e:1;
+ u32 rlc_mode_e:1;
+ u32 ch_8pix_ileav_e:1;
+ u32 start_code_e:1;
+ u32 reserved1:2;
+ /* sw_init_dc_match0 ? */
+ u32 inter_dblspeed:1;
+ u32 intra_dblspeed:1;
+ u32 intra_dbl3t:1;
+ u32 pref_sigchan:1;
+ u32 cache_en:1;
+ u32 reserved0:1;
+ /* dec_timeout_mode */
+ u32 dec_timeout:1;
+ } sw57;
+
+ struct {
+ u32 soft_rst:1;
+ u32 reverse0:31;
+ } sw58;
+
+ struct {
+ u32 reverse0:2;
+ /* sw_pflt_set0_tap2 */
+ u32 pred_bc_tap_0_2:10;
+ u32 pred_bc_tap_0_1:10;
+ /* pflt_set0_tap0 */
+ u32 pred_bc_tap_0_0:10;
+ } sw59;
+
+ struct {
+ u32 addit_ch_st_adr:32;
+ } sw60;
+
+ struct {
+ u32 qtable_base:32;
+ } sw61;
+
+ struct {
+ u32 dir_mv_base:32;
+ } sw62;
+
+ struct {
+ /* dec_out_st_adr */
+ u32 dec_out_base:32;
+ } sw63;
+
+ struct {
+ u32 rlc_vlc_base:32;
+ } sw64;
+
+ struct {
+ u32 refbuf_y_offset:9;
+ u32 reserve0:3;
+ u32 refbuf_fildpar_mode_e:1;
+ u32 refbuf_idcal_e:1;
+ u32 refbuf_picid:5;
+ u32 refbuf_thr_level:12;
+ u32 refbuf_e:1;
+ } sw65;
+
+ u32 sw66;
+ u32 sw67;
+
+ struct {
+ u32 refbuf_sum_bot:16;
+ u32 refbuf_sum_top:16;
+ } sw68;
+
+ struct {
+ u32 luma_sum_intra:16;
+ u32 refbuf_sum_hit:16;
+ } sw69;
+
+ struct {
+ u32 ycomp_mv_sum:22;
+ u32 reserve0:10;
+ } sw70;
+
+ u32 sw71;
+ u32 sw72;
+ u32 sw73;
+
+ struct {
+ u32 init_reflist_pf4:5;
+ u32 init_reflist_pf5:5;
+ u32 init_reflist_pf6:5;
+ u32 init_reflist_pf7:5;
+ u32 init_reflist_pf8:5;
+ u32 init_reflist_pf9:5;
+ u32 reverse0:2;
+ } sw74;
+
+ struct {
+ u32 init_reflist_pf10:5;
+ u32 init_reflist_pf11:5;
+ u32 init_reflist_pf12:5;
+ u32 init_reflist_pf13:5;
+ u32 init_reflist_pf14:5;
+ u32 init_reflist_pf15:5;
+ u32 reverse0:2;
+ } sw75;
+
+ struct {
+ u32 num_ref_idx0:16;
+ u32 num_ref_idx1:16;
+ } sw76;
+
+ struct {
+ u32 num_ref_idx2:16;
+ u32 num_ref_idx3:16;
+ } sw77;
+
+ struct {
+ u32 num_ref_idx4:16;
+ u32 num_ref_idx5:16;
+ } sw78;
+
+ struct {
+ u32 num_ref_idx6:16;
+ u32 num_ref_idx7:16;
+ } sw79;
+
+ struct {
+ u32 num_ref_idx8:16;
+ u32 num_ref_idx9:16;
+ } sw80;
+
+ struct {
+ u32 num_ref_idx10:16;
+ u32 num_ref_idx11:16;
+ } sw81;
+
+ struct {
+ u32 num_ref_idx12:16;
+ u32 num_ref_idx13:16;
+ } sw82;
+
+ struct {
+ u32 num_ref_idx14:16;
+ u32 num_ref_idx15:16;
+ } sw83;
+
+ /* Used by H.264 */
+ union {
+ u32 ref0_st_addr;
+ struct {
+ u32 ref0_closer_sel:1;
+ u32 ref0_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw84;
+
+ union {
+ u32 ref1_st_addr;
+ struct {
+ u32 ref1_closer_sel:1;
+ u32 ref1_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw85;
+
+ union {
+ u32 ref2_st_addr;
+ struct {
+ u32 ref2_closer_sel:1;
+ u32 ref2_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw86;
+
+ union {
+ u32 ref3_st_addr;
+ struct {
+ u32 ref3_closer_sel:1;
+ u32 ref3_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw87;
+
+ union {
+ u32 ref4_st_addr;
+ struct {
+ u32 ref4_closer_sel:1;
+ u32 ref4_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw88;
+
+ union {
+ u32 ref5_st_addr;
+ struct {
+ u32 ref5_closer_sel:1;
+ u32 ref5_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw89;
+
+ union {
+ u32 ref6_st_addr;
+ struct {
+ u32 ref6_closer_sel:1;
+ u32 ref6_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw90;
+
+ union {
+ u32 ref7_st_addr;
+ struct {
+ u32 ref7_closer_sel:1;
+ u32 ref7_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw91;
+
+ union {
+ u32 ref8_st_addr;
+ struct {
+ u32 ref8_closer_sel:1;
+ u32 ref8_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw92;
+
+ union {
+ u32 ref9_st_addr;
+ struct {
+ u32 ref9_closer_sel:1;
+ u32 ref9_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw93;
+
+ union {
+ u32 ref10_st_addr;
+ struct {
+ u32 ref10_closer_sel:1;
+ u32 ref10_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw94;
+
+ union {
+ u32 ref11_st_addr;
+ struct {
+ u32 ref11_closer_sel:1;
+ u32 ref11_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw95;
+
+ union {
+ u32 ref12_st_addr;
+ struct {
+ u32 ref12_closer_sel:1;
+ u32 ref12_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw96;
+
+ union {
+ u32 ref13_st_addr;
+ struct {
+ u32 ref13_closer_sel:1;
+ u32 ref13_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw97;
+
+ union {
+ u32 ref14_st_addr;
+ struct {
+ u32 ref14_closer_sel:1;
+ u32 ref14_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw98;
+
+ /* Used by H.264 */
+ union {
+ u32 ref15_st_addr;
+ struct {
+ u32 ref15_closer_sel:1;
+ u32 ref15_field_en:1;
+ u32 reverse0:30;
+ };
+ } sw99;
+
+ struct {
+ u32 init_reflist_df0:5;
+ u32 init_reflist_df1:5;
+ u32 init_reflist_df2:5;
+ u32 init_reflist_df3:5;
+ u32 init_reflist_df4:5;
+ u32 init_reflist_df5:5;
+ u32 reverse0:2;
+ } sw100;
+
+ struct {
+ u32 init_reflist_df6:5;
+ u32 init_reflist_df7:5;
+ u32 init_reflist_df8:5;
+ u32 init_reflist_df9:5;
+ u32 init_reflist_df10:5;
+ u32 init_reflist_df11:5;
+ u32 reverse0:2;
+ } sw101;
+
+ struct {
+ u32 init_reflist_df12:5;
+ u32 init_reflist_df13:5;
+ u32 init_reflist_df14:5;
+ u32 init_reflist_df15:5;
+ u32 reverse0:12;
+ } sw102;
+
+ struct {
+ u32 init_reflist_db0:5;
+ u32 init_reflist_db1:5;
+ u32 init_reflist_db2:5;
+ u32 init_reflist_db3:5;
+ u32 init_reflist_db4:5;
+ u32 init_reflist_db5:5;
+ u32 reverse0:2;
+ } sw103;
+
+ struct {
+ u32 init_reflist_db6:5;
+ u32 init_reflist_db7:5;
+ u32 init_reflist_db8:5;
+ u32 init_reflist_db9:5;
+ u32 init_reflist_db10:5;
+ u32 init_reflist_db11:5;
+ u32 reverse0:2;
+ } sw104;
+
+ struct {
+ u32 init_reflist_db12:5;
+ u32 init_reflist_db13:5;
+ u32 init_reflist_db14:5;
+ u32 init_reflist_db15:5;
+ u32 reverse0:12;
+ } sw105;
+
+ struct {
+ u32 init_reflist_pf0:5;
+ u32 init_reflist_pf1:5;
+ u32 init_reflist_pf2:5;
+ u32 init_reflist_pf3:5;
+ u32 reverse0:12;
+ } sw106;
+
+ struct {
+ u32 refpic_term_flag:32;
+ } sw107;
+
+ struct {
+ u32 refpic_valid_flag:32;
+ } sw108;
+
+ struct {
+ u32 strm_start_bit:6;
+ u32 reverse0:26;
+ } sw109;
+
+ struct {
+ u32 pic_mb_w:9;
+ u32 pic_mb_h:8;
+ u32 flt_offset_cb_qp:5;
+ u32 flt_offset_cr_qp:5;
+ u32 reverse0:5;
+ } sw110;
+
+ struct {
+ u32 max_refnum:5;
+ u32 reverse0:11;
+ u32 wp_bslice_sel:2;
+ u32 reverse1:14;
+ } sw111;
+
+ struct {
+ u32 curfrm_num:16;
+ u32 cur_frm_len:5;
+ u32 reverse0:9;
+ u32 rpcp_flag:1;
+ u32 dblk_ctrl_flag:1;
+ } sw112;
+
+ struct {
+ u32 idr_pic_id:16;
+ u32 refpic_mk_len:11;
+ u32 reverse0:5;
+ } sw113;
+
+ struct {
+ u32 poc_field_len:8;
+ u32 reverse0:6;
+ u32 max_refidx0:5;
+ u32 max_refidx1:5;
+ u32 pps_id:5;
+ } sw114;
+
+ struct {
+ u32 fieldpic_flag_exist:1;
+ u32 scl_matrix_en:1;
+ u32 tranf_8x8_flag_en:1;
+ u32 const_intra_en:1;
+ u32 weight_pred_en:1;
+ u32 cabac_en:1;
+ u32 monochr_en:1;
+ u32 dlmv_method_en:1;
+ u32 idr_pic_flag:1;
+ u32 reverse0:23;
+ } sw115;
+
+ u32 sw116_158[43];
+
+ struct {
+#if 0
+ union {
+ struct avs {
+ u32 pic_refer_flag:1;
+ u32 reserved0:5;
+ };
+
+ struct vc1 {
+ u32 pic_mb_w_ext:3;
+ u32 pic_mb_h_ext:3;
+ };
+
+ struct h264 {
+ u32 ref_frames:5;
+ u32 reserved0:1;
+ };
+
+ struct mpeg {
+ u32 reserved0:5;
+ u32 topfieldfirst_e:1;
+ };
+ };
+#else
+ u32 ref_frames:5;
+ u32 topfieldfirst_e:1;
+#endif
+ u32 alt_scan_e:1;
+ u32 mb_height_off:4;
+ u32 pic_mb_height_p:8;
+ /* Used by VC-1 only */
+ u32 mb_width_off:4;
+ u32 pic_mb_width:9;
+ } sw120;
+
+ u32 sw121;
+
+ struct {
+ u32 frame_pred_dct:1;
+ u32 intra_vlc_tab:1;
+ u32 intra_dc_prec:1;
+ u32 con_mv_e:1;
+ u32 reserved0:19;
+ u32 qscale_type:1;
+ u32 reserved1:1;
+ u32 strm_start_bit:6;
+ } sw122;
+
+ u32 sw123;
+ u32 sw124;
+ u32 sw125;
+ u32 sw126;
+ u32 sw127;
+ u32 sw128;
+ u32 sw129;
+ u32 sw130;
+
+ struct {
+ u32 refer0_topc_e:1;
+ u32 refer0_field_e:1;
+ u32 refer0_base:30;
+ } sw131;
+
+ u32 sw132;
+ u32 sw133;
+
+ struct {
+ u32 refer2_topc_e:1;
+ u32 refer2_field_e:1;
+ u32 refer2_base:30;
+ } sw134;
+
+ struct {
+ u32 refer3_topc_e:1;
+ u32 refer3_field_e:1;
+ u32 refer3_base:30;
+ } sw135;
+
+ struct {
+ u32 reserved0:1;
+ u32 mv_accuracy_bwd:1;
+ u32 mv_accuracy_fwd:1;
+ u32 fcode_bwd_ver:4;
+ u32 fcode_bwd_hor:4;
+ u32 fcode_fwd_ver:4;
+ u32 fcode_fwd_hor:4;
+ u32 alt_scan_flag_e:1;
+ u32 reserved1:12;
+ } sw136;
+
+ u32 sw137;
+ u32 sw138;
+ u32 sw139;
+ u32 sw140;
+ u32 sw141;
+ u32 sw142;
+ u32 sw143;
+ u32 sw144;
+ u32 sw145;
+ u32 sw146;
+ u32 sw147;
+
+ struct {
+ u32 refer1_topc_e:1;
+ u32 refer1_field_e:1;
+ u32 refer1_base:30;
+ } sw148;
+
+ u32 sw149_sw158[10];
+} __attribute__((packed));
+
+#endif