CHROMIUM: [media] rockchip-vpu: reconstructs for futher chips
authorJeffy Chen <jeffy.chen@rock-chips.com>
Thu, 2 Jun 2016 07:05:52 +0000 (15:05 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 30 Jun 2016 12:03:12 +0000 (20:03 +0800)
Change-Id: Ia88f45b37a1af829723e6b8cb9d8ff3cb5f54530
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
drivers/media/platform/rockchip-vpu/rockchip_vpu.c
drivers/media/platform/rockchip-vpu/rockchip_vpu_common.h
drivers/media/platform/rockchip-vpu/rockchip_vpu_dec.c
drivers/media/platform/rockchip-vpu/rockchip_vpu_enc.c
drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.c

index 4b0b184a6b8e680a7e2063d5ae297e1db242a47f..e7bb63562e2f6ca16dd82ef779ac0694ddb03627 100644 (file)
@@ -98,7 +98,8 @@ rockchip_vpu_encode_after_decode_war(struct rockchip_vpu_ctx *ctx)
 {
        struct rockchip_vpu_dev *dev = ctx->dev;
 
-       if (dev->was_decoding && rockchip_vpu_ctx_is_encoder(ctx))
+       if (dev->dummy_encode_ctx &&
+                       dev->was_decoding && rockchip_vpu_ctx_is_encoder(ctx))
                return dev->dummy_encode_ctx;
 
        return ctx;
@@ -587,6 +588,8 @@ static const struct v4l2_file_operations rockchip_vpu_fops = {
  * Platform driver.
  */
 
+static void* rockchip_get_drv_data(struct platform_device *pdev);
+
 static int rockchip_vpu_probe(struct platform_device *pdev)
 {
        struct rockchip_vpu_dev *vpu = NULL;
@@ -608,9 +611,11 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&vpu->ready_ctxs);
        init_waitqueue_head(&vpu->run_wq);
 
+       vpu->variant = rockchip_get_drv_data(pdev);
+
        ret = rockchip_vpu_hw_probe(vpu);
        if (ret) {
-               dev_err(&pdev->dev, "vcodec_hw_probe failed\n");
+               dev_err(&pdev->dev, "rockchip_vpu_hw_probe failed\n");
                goto err_hw_probe;
        }
 
@@ -644,13 +649,20 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, vpu);
 
-       ret = rockchip_vpu_enc_init_dummy_ctx(vpu);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to create dummy encode context\n");
-               goto err_dummy_enc;
+       /* workaround for rk3288 codecs */
+       if (vpu->variant->codecs == RK3288_CODECS) {
+               ret = rockchip_vpu_enc_init_dummy_ctx(vpu);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "Failed to create dummy encode context\n");
+                       goto err_dummy_enc;
+               }
        }
 
        /* encoder */
+       if (!(vpu->variant->codecs & ROCKCHIP_VPU_ENCODERS))
+               goto no_encoder;
+
        vfd = video_device_alloc();
        if (!vfd) {
                v4l2_err(&vpu->v4l2_dev, "Failed to allocate video device\n");
@@ -680,7 +692,11 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
                "Rockchip VPU encoder registered as /vpu/video%d\n",
                vfd->num);
 
+no_encoder:
        /* decoder */
+       if (!(vpu->variant->codecs & ROCKCHIP_VPU_DECODERS))
+               goto no_decoder;
+
        vfd = video_device_alloc();
        if (!vfd) {
                v4l2_err(&vpu->v4l2_dev, "Failed to allocate video device\n");
@@ -710,6 +726,7 @@ static int rockchip_vpu_probe(struct platform_device *pdev)
                "Rockchip VPU decoder registered as /vpu/video%d\n",
                vfd->num);
 
+no_decoder:
        vpu_debug_leave();
 
        return 0;
@@ -764,8 +781,21 @@ static int rockchip_vpu_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* Supported VPU variants. */
+static const struct rockchip_vpu_variant rk3288_vpu_variant = {
+       .name = "Rk3288 vpu",
+       .codecs = RK3288_CODECS,
+       .enc_offset = 0x0,
+       .enc_reg_num = 164,
+       .dec_offset = 0x400,
+       .dec_reg_num = 60 + 41,
+};
+
 static struct platform_device_id vpu_driver_ids[] = {
-       { .name = "rk3288-vpu", },
+       {
+               .name = "rk3288-vpu",
+               .driver_data = (unsigned long)&rk3288_vpu_variant,
+       },
        { /* sentinel */ }
 };
 
@@ -773,12 +803,27 @@ MODULE_DEVICE_TABLE(platform, vpu_driver_ids);
 
 #ifdef CONFIG_OF
 static const struct of_device_id of_rockchip_vpu_match[] = {
-       { .compatible = "rockchip,rk3288-vpu", },
+       { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, of_rockchip_vpu_match);
 #endif
 
+static void* rockchip_get_drv_data(struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(of_rockchip_vpu_match,
+                                                         pdev->dev.of_node);
+               if (match)
+                       return (void *)match->data;
+       }
+#endif
+
+       return (void *)platform_get_device_id(pdev)->driver_data;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int rockchip_vpu_suspend(struct device *dev)
 {
@@ -812,7 +857,9 @@ static struct platform_driver rockchip_vpu_driver = {
        .driver = {
                   .name = ROCKCHIP_VPU_NAME,
                   .owner = THIS_MODULE,
+#ifdef CONFIG_OF
                   .of_match_table = of_match_ptr(of_rockchip_vpu_match),
+#endif
                   .pm = &rockchip_vpu_pm_ops,
        },
 };
index 71b805b80c0ae2df80d588f7058205d8d67968cc..2f5ccf0055aca4572dd7af9be0f955e044de0c21 100644 (file)
 #define MB_WIDTH(x_size)               DIV_ROUND_UP(x_size, MB_DIM)
 #define MB_HEIGHT(y_size)              DIV_ROUND_UP(y_size, MB_DIM)
 
-struct rockchip_vpu_variant;
 struct rockchip_vpu_ctx;
 struct rockchip_vpu_codec_ops;
 
+/**
+ * struct rockchip_vpu_variant - information about VPU hardware variant
+ *
+ * @hw_id:             Top 16 bits (product ID) of hardware ID register.
+ * @name:              Vpu name.
+ * @codecs:            Supported codecs of this vpu.
+ * @enc_offset:                Offset from VPU base to encoder registers.
+ * @enc_reg_num:       Number of registers of encoder block.
+ * @dec_offset:                Offset from VPU base to decoder registers.
+ * @dec_reg_num:       Number of registers of decoder block.
+ */
+struct rockchip_vpu_variant {
+       char *name;
+       unsigned codecs;
+       unsigned enc_offset;
+       unsigned enc_reg_num;
+       unsigned dec_offset;
+       unsigned dec_reg_num;
+};
+
 /**
  * enum rockchip_vpu_codec_mode - codec operating mode.
- * @RK_VPU_CODEC_NONE: No operating mode. Used for RAW video formats.
+ * @RK_VPU_CODEC_NONE:         Used for RAW video formats.
  * @RK3288_VPU_CODEC_H264D:    Rk3288 H264 decoder.
  * @RK3288_VPU_CODEC_VP8D:     Rk3288 VP8 decoder.
  * @RK3288_VPU_CODEC_VP8E:     Rk3288 VP8 encoder.
  */
 enum rockchip_vpu_codec_mode {
-       RK_VPU_CODEC_NONE = -1,
-       RK3288_VPU_CODEC_H264D,
-       RK3288_VPU_CODEC_VP8D,
-       RK3288_VPU_CODEC_VP8E
+       RK_VPU_CODEC_NONE       = (1 << 0),
+       RK3288_VPU_CODEC_H264D  = (1 << 1),
+       RK3288_VPU_CODEC_VP8D   = (1 << 2),
+       RK3288_VPU_CODEC_VP8E   = (1 << 3),
 };
 
+#define ROCKCHIP_VPU_DECODERS  (RK3288_VPU_CODEC_H264D | RK3288_VPU_CODEC_VP8D)
+#define ROCKCHIP_VPU_ENCODERS  (RK3288_VPU_CODEC_VP8E)
+
+#define RK3288_CODECS          (RK_VPU_CODEC_NONE | RK3288_VPU_CODEC_H264D | RK3288_VPU_CODEC_VP8D | RK3288_VPU_CODEC_VP8E)
+
 /**
  * enum rockchip_vpu_plane - indices of planes inside a VB2 buffer.
  * @PLANE_Y:           Plane containing luminance data (also denoted as Y).
@@ -138,8 +162,8 @@ enum rockchip_vpu_state {
  *                     (for allocations without kernel mapping).
  * @alloc_ctx_vm:      VB2 allocator context
  *                     (for allocations with kernel mapping).
- * @aclk_vcodec:       Handle of ACLK clock.
- * @hclk_vcodec:       Handle of HCLK clock.
+ * @aclk:              Handle of ACLK clock.
+ * @hclk:              Handle of HCLK clock.
  * @base:              Mapped address of VPU registers.
  * @enc_base:          Mapped address of VPU encoder register for convenience.
  * @dec_base:          Mapped address of VPU decoder register for convenience.
@@ -168,8 +192,8 @@ struct rockchip_vpu_dev {
        struct device *dev;
        void *alloc_ctx;
        void *alloc_ctx_vm;
-       struct clk *aclk_vcodec;
-       struct clk *hclk_vcodec;
+       struct clk *aclk;
+       struct clk *hclk;
        void __iomem *base;
        void __iomem *enc_base;
        void __iomem *dec_base;
@@ -457,6 +481,13 @@ rockchip_vpu_ctx_is_dummy_encode(struct rockchip_vpu_ctx *ctx)
        return ctx == dev->dummy_encode_ctx;
 }
 
+static inline bool
+rockchip_vpu_dev_codec_support(struct rockchip_vpu_dev *dev,
+                              enum rockchip_vpu_codec_mode codec_mode)
+{
+       return !!(codec_mode & dev->variant->codecs);
+}
+
 int rockchip_vpu_ctrls_setup(struct rockchip_vpu_ctx *ctx,
                           const struct v4l2_ctrl_ops *ctrl_ops,
                           struct rockchip_vpu_control *controls,
index 7e7e7242b8860e146ed5d35321c835b51c6b0a01..e1e1452de6f78538b9a71344e1f707a11ef305c9 100644 (file)
@@ -54,26 +54,29 @@ static struct rockchip_vpu_fmt formats[] = {
                .depth = { 12 },
        },
        {
-               .name = "Slices of H264 Encoded Stream",
+               .name = "Slices of H264 Encoded Stream(RK3288)",
                .fourcc = V4L2_PIX_FMT_H264_SLICE,
                .codec_mode = RK3288_VPU_CODEC_H264D,
                .num_planes = 1,
        },
        {
-               .name = "Frames of VP8 Encoded Stream",
+               .name = "Frames of VP8 Encoded Stream(RK3288)",
                .fourcc = V4L2_PIX_FMT_VP8_FRAME,
                .codec_mode = RK3288_VPU_CODEC_VP8D,
                .num_planes = 1,
        },
 };
 
-static struct rockchip_vpu_fmt *find_format(u32 fourcc, bool bitstream)
+static struct rockchip_vpu_fmt *find_format(struct rockchip_vpu_dev *dev,
+                                           u32 fourcc, bool bitstream)
 {
        unsigned int i;
 
        vpu_debug_enter();
 
        for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               if (!rockchip_vpu_dev_codec_support(dev, formats[i].codec_mode))
+                       continue;
                if (formats[i].fourcc == fourcc &&
                    !!bitstream == (formats[i].codec_mode != RK_VPU_CODEC_NONE))
                        return &formats[i];
@@ -182,6 +185,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 static int vidioc_enum_framesizes(struct file *file, void *prov,
                                  struct v4l2_frmsizeenum *fsize)
 {
+       struct rockchip_vpu_dev *dev = video_drvdata(file);
        struct v4l2_frmsize_stepwise *s = &fsize->stepwise;
        struct rockchip_vpu_fmt *fmt;
 
@@ -191,7 +195,7 @@ static int vidioc_enum_framesizes(struct file *file, void *prov,
                return -EINVAL;
        }
 
-       fmt = find_format(fsize->pixel_format, true);
+       fmt = find_format(dev, fsize->pixel_format, true);
        if (!fmt) {
                vpu_debug(0, "unsupported bitstream format (%08x)\n",
                                fsize->pixel_format);
@@ -210,14 +214,17 @@ static int vidioc_enum_framesizes(struct file *file, void *prov,
        return 0;
 }
 
-static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool out)
+static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, bool out)
 {
+       struct rockchip_vpu_dev *dev = video_drvdata(file);
        struct rockchip_vpu_fmt *fmt;
        int i, j = 0;
 
        vpu_debug_enter();
 
        for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (!rockchip_vpu_dev_codec_support(dev, formats[i].codec_mode))
+                       continue;
                if (out && formats[i].codec_mode == RK_VPU_CODEC_NONE)
                        continue;
                else if (!out && (formats[i].codec_mode != RK_VPU_CODEC_NONE))
@@ -249,13 +256,13 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool out)
 static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
                                          struct v4l2_fmtdesc *f)
 {
-       return vidioc_enum_fmt(f, false);
+       return vidioc_enum_fmt(file, f, false);
 }
 
 static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *priv,
                                          struct v4l2_fmtdesc *f)
 {
-       return vidioc_enum_fmt(f, true);
+       return vidioc_enum_fmt(file, f, true);
 }
 
 static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
@@ -287,6 +294,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 
 static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
+       struct rockchip_vpu_dev *dev = video_drvdata(file);
        struct rockchip_vpu_fmt *fmt;
        struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
        char str[5];
@@ -297,7 +305,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                vpu_debug(4, "%s\n", fmt2str(f->fmt.pix_mp.pixelformat, str));
 
-               fmt = find_format(pix_fmt_mp->pixelformat, true);
+               fmt = find_format(dev, pix_fmt_mp->pixelformat, true);
                if (!fmt) {
                        vpu_err("failed to try output format\n");
                        return -EINVAL;
@@ -314,7 +322,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                vpu_debug(4, "%s\n", fmt2str(f->fmt.pix_mp.pixelformat, str));
 
-               fmt = find_format(pix_fmt_mp->pixelformat, false);
+               fmt = find_format(dev, pix_fmt_mp->pixelformat, false);
                if (!fmt) {
                        vpu_err("failed to try capture format\n");
                        return -EINVAL;
@@ -350,6 +358,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
        struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
        struct rockchip_vpu_ctx *ctx = fh_to_ctx(priv);
+       struct rockchip_vpu_dev *dev = ctx->dev;
        unsigned int mb_width, mb_height;
        struct rockchip_vpu_fmt *fmt;
        int ret = 0;
@@ -379,7 +388,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                if (ret)
                        goto out;
 
-               ctx->vpu_src_fmt = find_format(pix_fmt_mp->pixelformat, true);
+               ctx->vpu_src_fmt = find_format(dev, pix_fmt_mp->pixelformat, true);
                ctx->src_fmt = *pix_fmt_mp;
                break;
 
@@ -408,7 +417,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                if (ret)
                        goto out;
 
-               fmt = find_format(pix_fmt_mp->pixelformat, false);
+               fmt = find_format(dev, pix_fmt_mp->pixelformat, false);
                ctx->vpu_dst_fmt = fmt;
 
                mb_width = MB_WIDTH(pix_fmt_mp->width);
@@ -1138,8 +1147,10 @@ static const struct rockchip_vpu_run_ops rockchip_vpu_dec_run_ops = {
 
 int rockchip_vpu_dec_init(struct rockchip_vpu_ctx *ctx)
 {
-       ctx->vpu_src_fmt = find_format(DEF_SRC_FMT_DEC, false);
-       ctx->vpu_dst_fmt = find_format(DEF_DST_FMT_DEC, true);
+       struct rockchip_vpu_dev *vpu = ctx->dev;
+
+       ctx->vpu_src_fmt = find_format(vpu, DEF_SRC_FMT_DEC, false);
+       ctx->vpu_dst_fmt = find_format(vpu, DEF_DST_FMT_DEC, true);
 
        ctx->run_ops = &rockchip_vpu_dec_run_ops;
 
index 0a10392a0fee714874a35107ac48387acc287767..dd5c1770284a4ab0de4d9c5ba31a2a47d1cf7924 100644 (file)
@@ -97,13 +97,15 @@ static struct rockchip_vpu_fmt formats[] = {
        },
 };
 
-static struct rockchip_vpu_fmt *find_format(u32 fourcc, bool bitstream)
+static struct rockchip_vpu_fmt *find_format(struct rockchip_vpu_dev *dev, u32 fourcc, bool bitstream)
 {
        unsigned int i;
 
        vpu_debug_enter();
 
        for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               if (!rockchip_vpu_dev_codec_support(dev, formats[i].codec_mode))
+                       continue;
                if (formats[i].fourcc != fourcc)
                        continue;
                if (bitstream && formats[i].codec_mode != RK_VPU_CODEC_NONE)
@@ -360,6 +362,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 static int vidioc_enum_framesizes(struct file *file, void *prov,
                                  struct v4l2_frmsizeenum *fsize)
 {
+       struct rockchip_vpu_dev *dev = video_drvdata(file);
        struct v4l2_frmsize_stepwise *s = &fsize->stepwise;
        struct rockchip_vpu_fmt *fmt;
 
@@ -369,7 +372,7 @@ static int vidioc_enum_framesizes(struct file *file, void *prov,
                return -EINVAL;
        }
 
-       fmt = find_format(fsize->pixel_format, true);
+       fmt = find_format(dev, fsize->pixel_format, true);
        if (!fmt) {
                vpu_debug(0, "unsupported bitstream format (%08x)\n",
                                fsize->pixel_format);
@@ -388,14 +391,17 @@ static int vidioc_enum_framesizes(struct file *file, void *prov,
        return 0;
 }
 
-static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool out)
+static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, bool out)
 {
+       struct rockchip_vpu_dev *dev = video_drvdata(file);
        struct rockchip_vpu_fmt *fmt;
        int i, j = 0;
 
        vpu_debug_enter();
 
        for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (!rockchip_vpu_dev_codec_support(dev, formats[i].codec_mode))
+                       continue;
                if (out && formats[i].codec_mode != RK_VPU_CODEC_NONE)
                        continue;
                else if (!out && formats[i].codec_mode == RK_VPU_CODEC_NONE)
@@ -427,13 +433,13 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool out)
 static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
                                          struct v4l2_fmtdesc *f)
 {
-       return vidioc_enum_fmt(f, false);
+       return vidioc_enum_fmt(file, f, false);
 }
 
 static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *priv,
                                          struct v4l2_fmtdesc *f)
 {
-       return vidioc_enum_fmt(f, true);
+       return vidioc_enum_fmt(file, f, true);
 }
 
 static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
@@ -465,6 +471,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 
 static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
+       struct rockchip_vpu_dev *dev = video_drvdata(file);
        struct rockchip_vpu_fmt *fmt;
        struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
        char str[5];
@@ -475,7 +482,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                vpu_debug(4, "%s\n", fmt2str(f->fmt.pix_mp.pixelformat, str));
 
-               fmt = find_format(pix_fmt_mp->pixelformat, true);
+               fmt = find_format(dev, pix_fmt_mp->pixelformat, true);
                if (!fmt) {
                        vpu_err("failed to try capture format\n");
                        return -EINVAL;
@@ -492,7 +499,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                vpu_debug(4, "%s\n", fmt2str(f->fmt.pix_mp.pixelformat, str));
 
-               fmt = find_format(pix_fmt_mp->pixelformat, false);
+               fmt = find_format(dev, pix_fmt_mp->pixelformat, false);
                if (!fmt) {
                        vpu_err("failed to try output format\n");
                        return -EINVAL;
@@ -546,6 +553,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
        struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
        struct rockchip_vpu_ctx *ctx = fh_to_ctx(priv);
+       struct rockchip_vpu_dev *dev = ctx->dev;
        unsigned int mb_width, mb_height;
        struct rockchip_vpu_fmt *fmt;
        int ret = 0;
@@ -574,7 +582,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                if (ret)
                        goto out;
 
-               ctx->vpu_dst_fmt = find_format(pix_fmt_mp->pixelformat, true);
+               ctx->vpu_dst_fmt = find_format(dev, pix_fmt_mp->pixelformat, true);
                ctx->dst_fmt = *pix_fmt_mp;
                break;
 
@@ -593,7 +601,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                if (ret)
                        goto out;
 
-               fmt = find_format(pix_fmt_mp->pixelformat, false);
+               fmt = find_format(dev, pix_fmt_mp->pixelformat, false);
                ctx->vpu_src_fmt = fmt;
 
                mb_width = MB_WIDTH(pix_fmt_mp->width);
@@ -1313,14 +1321,16 @@ static void rockchip_vpu_enc_prepare_run(struct rockchip_vpu_ctx *ctx)
 
        v4l2_ctrl_apply_store(&ctx->ctrl_handler, config_store);
 
-       memcpy(ctx->run.dst->vp8e.header,
-               get_ctrl_ptr(ctx, ROCKCHIP_VPU_ENC_CTRL_HEADER),
-               ROCKCHIP_HEADER_SIZE);
-       ctx->run.vp8e.reg_params = get_ctrl_ptr(ctx,
-               ROCKCHIP_VPU_ENC_CTRL_REG_PARAMS);
-       memcpy(ctx->run.priv_src.cpu,
-               get_ctrl_ptr(ctx, ROCKCHIP_VPU_ENC_CTRL_HW_PARAMS),
-               ROCKCHIP_HW_PARAMS_SIZE);
+       if (ctx->vpu_dst_fmt->fourcc == V4L2_PIX_FMT_VP8) {
+               memcpy(ctx->run.dst->vp8e.header,
+                       get_ctrl_ptr(ctx, ROCKCHIP_VPU_ENC_CTRL_HEADER),
+                       ROCKCHIP_HEADER_SIZE);
+               ctx->run.vp8e.reg_params = get_ctrl_ptr(ctx,
+                       ROCKCHIP_VPU_ENC_CTRL_REG_PARAMS);
+               memcpy(ctx->run.priv_src.cpu,
+                       get_ctrl_ptr(ctx, ROCKCHIP_VPU_ENC_CTRL_HW_PARAMS),
+                       ROCKCHIP_HW_PARAMS_SIZE);
+       }
 }
 
 static const struct rockchip_vpu_run_ops rockchip_vpu_enc_run_ops = {
@@ -1332,8 +1342,8 @@ int rockchip_vpu_enc_init(struct rockchip_vpu_ctx *ctx)
        struct rockchip_vpu_dev *vpu = ctx->dev;
        int ret;
 
-       ctx->vpu_src_fmt = find_format(DEF_SRC_FMT_ENC, false);
-       ctx->vpu_dst_fmt = find_format(DEF_DST_FMT_ENC, true);
+       ctx->vpu_src_fmt = find_format(vpu, DEF_SRC_FMT_ENC, false);
+       ctx->vpu_dst_fmt = find_format(vpu, DEF_DST_FMT_ENC, true);
 
        ret = rockchip_vpu_aux_buf_alloc(vpu, &ctx->run.priv_src,
                                        ROCKCHIP_HW_PARAMS_SIZE);
@@ -1406,7 +1416,7 @@ int rockchip_vpu_enc_init_dummy_ctx(struct rockchip_vpu_dev *dev)
 
        ctx->dev = dev;
 
-       ctx->vpu_src_fmt = find_format(DUMMY_SRC_FMT, false);
+       ctx->vpu_src_fmt = find_format(dev, DUMMY_SRC_FMT, false);
        ctx->src_fmt.width = DUMMY_W;
        ctx->src_fmt.height = DUMMY_H;
        ctx->src_fmt.pixelformat = ctx->vpu_src_fmt->fourcc;
@@ -1415,7 +1425,7 @@ int rockchip_vpu_enc_init_dummy_ctx(struct rockchip_vpu_dev *dev)
        calculate_plane_sizes(ctx->vpu_src_fmt, ctx->src_fmt.width,
                                ctx->src_fmt.height, &ctx->src_fmt);
 
-       ctx->vpu_dst_fmt = find_format(DUMMY_DST_FMT, true);
+       ctx->vpu_dst_fmt = find_format(dev, DUMMY_DST_FMT, true);
        ctx->dst_fmt.width = ctx->src_fmt.width;
        ctx->dst_fmt.height = ctx->src_fmt.height;
        ctx->dst_fmt.pixelformat = ctx->vpu_dst_fmt->fourcc;
@@ -1495,6 +1505,9 @@ void rockchip_vpu_enc_free_dummy_ctx(struct rockchip_vpu_dev *dev)
        struct rockchip_vpu_ctx *ctx = dev->dummy_encode_ctx;
        int i;
 
+       if (!ctx)
+               return;
+
        rockchip_vpu_deinit(ctx);
 
        for (i = 0; i < ctx->src_fmt.num_planes; ++i)
index 3959d9f2c957e2a0b2ca6761b52187968fd8f90a..d97ac7f90a8bc626cf17c7f43cf77fb81d3cd5c6 100644 (file)
 #define VP8_FRAME_TAG_LENGTH_SHIFT              5
 #define VP8_FRAME_TAG_LENGTH_MASK               (0x7ffff << 5)
 
-/**
- * struct rockchip_vpu_variant - information about VPU hardware variant
- *
- * @hw_id:             Top 16 bits (product ID) of hardware ID register.
- * @enc_offset:                Offset from VPU base to encoder registers.
- * @enc_reg_num:       Number of registers of encoder block.
- * @dec_offset:                Offset from VPU base to decoder registers.
- * @dec_reg_num:       Number of registers of decoder block.
- */
-struct rockchip_vpu_variant {
-       u16 hw_id;
-       unsigned enc_offset;
-       unsigned enc_reg_num;
-       unsigned dec_offset;
-       unsigned dec_reg_num;
-};
-
-/* Supported VPU variants. */
-static const struct rockchip_vpu_variant rockchip_vpu_variants[] = {
-       {
-               .hw_id = 0x4831,
-               .enc_offset = 0x0,
-               .enc_reg_num = 164,
-               .dec_offset = 0x400,
-               .dec_reg_num = 60 + 41,
-       },
-};
-
 /**
  * struct rockchip_vpu_codec_ops - codec mode specific operations
  *
+ * @codec_mode:        Codec mode related to this format. See
+ *             enum rockchip_vpu_codec_mode.
  * @init:      Prepare for streaming. Called from VB2 .start_streaming()
  *             when streaming from both queues is being enabled.
  * @exit:      Clean-up after streaming. Called from VB2 .stop_streaming()
@@ -82,6 +56,8 @@ static const struct rockchip_vpu_variant rockchip_vpu_variants[] = {
  * @reset:     Reset the hardware in case of a timeout.
  */
 struct rockchip_vpu_codec_ops {
+       enum rockchip_vpu_codec_mode codec_mode;
+
        int (*init)(struct rockchip_vpu_ctx *);
        void (*exit)(struct rockchip_vpu_ctx *);
 
@@ -95,25 +71,6 @@ struct rockchip_vpu_codec_ops {
  * Hardware control routines.
  */
 
-static int rockchip_vpu_identify(struct rockchip_vpu_dev *vpu)
-{
-       u32 hw_id;
-       int i;
-
-       hw_id = readl(vpu->base) >> 16;
-
-       dev_info(vpu->dev, "Read hardware ID: %x\n", hw_id);
-
-       for (i = 0; i < ARRAY_SIZE(rockchip_vpu_variants); ++i) {
-               if (hw_id == rockchip_vpu_variants[i].hw_id) {
-                       vpu->variant = &rockchip_vpu_variants[i];
-                       return 0;
-               }
-       }
-
-       return -ENOENT;
-}
-
 void rockchip_vpu_power_on(struct rockchip_vpu_dev *vpu)
 {
        vpu_debug_enter();
@@ -261,16 +218,16 @@ int rockchip_vpu_hw_probe(struct rockchip_vpu_dev *vpu)
 
        INIT_DELAYED_WORK(&vpu->watchdog_work, rockchip_vpu_watchdog);
 
-       vpu->aclk_vcodec = devm_clk_get(vpu->dev, "aclk_vcodec");
-       if (IS_ERR(vpu->aclk_vcodec)) {
-               dev_err(vpu->dev, "failed to get aclk_vcodec\n");
-               return PTR_ERR(vpu->aclk_vcodec);
+       vpu->aclk = devm_clk_get(vpu->dev, "aclk");
+       if (IS_ERR(vpu->aclk)) {
+               dev_err(vpu->dev, "failed to get aclk\n");
+               return PTR_ERR(vpu->aclk);
        }
 
-       vpu->hclk_vcodec = devm_clk_get(vpu->dev, "hclk_vcodec");
-       if (IS_ERR(vpu->hclk_vcodec)) {
-               dev_err(vpu->dev, "failed to get hclk_vcodec\n");
-               return PTR_ERR(vpu->hclk_vcodec);
+       vpu->hclk = devm_clk_get(vpu->dev, "hclk");
+       if (IS_ERR(vpu->hclk)) {
+               dev_err(vpu->dev, "failed to get hclk\n");
+               return PTR_ERR(vpu->hclk);
        }
 
        /*
@@ -278,21 +235,15 @@ int rockchip_vpu_hw_probe(struct rockchip_vpu_dev *vpu)
         *
         * VP8 encoding 1280x720@1.2Mbps 200 MHz: 39 fps, 400: MHz 77 fps
         */
-       clk_set_rate(vpu->aclk_vcodec, 400*1000*1000);
+       clk_set_rate(vpu->aclk, 400*1000*1000);
 
        res = platform_get_resource(vpu->pdev, IORESOURCE_MEM, 0);
        vpu->base = devm_ioremap_resource(vpu->dev, res);
        if (IS_ERR(vpu->base))
                return PTR_ERR(vpu->base);
 
-       clk_prepare_enable(vpu->aclk_vcodec);
-       clk_prepare_enable(vpu->hclk_vcodec);
-
-       ret = rockchip_vpu_identify(vpu);
-       if (ret < 0) {
-               dev_err(vpu->dev, "failed to identify hardware variant\n");
-               goto err_power;
-       }
+       clk_prepare_enable(vpu->aclk);
+       clk_prepare_enable(vpu->hclk);
 
        vpu->enc_base = vpu->base + vpu->variant->enc_offset;
        vpu->dec_base = vpu->base + vpu->variant->dec_offset;
@@ -344,8 +295,8 @@ int rockchip_vpu_hw_probe(struct rockchip_vpu_dev *vpu)
 err_iommu:
        rockchip_vpu_iommu_cleanup(vpu);
 err_power:
-       clk_disable_unprepare(vpu->hclk_vcodec);
-       clk_disable_unprepare(vpu->aclk_vcodec);
+       clk_disable_unprepare(vpu->hclk);
+       clk_disable_unprepare(vpu->aclk);
 
        return ret;
 }
@@ -356,12 +307,13 @@ void rockchip_vpu_hw_remove(struct rockchip_vpu_dev *vpu)
 
        pm_runtime_disable(vpu->dev);
 
-       clk_disable_unprepare(vpu->hclk_vcodec);
-       clk_disable_unprepare(vpu->aclk_vcodec);
+       clk_disable_unprepare(vpu->hclk);
+       clk_disable_unprepare(vpu->aclk);
 }
 
 static const struct rockchip_vpu_codec_ops mode_ops[] = {
-       [RK3288_VPU_CODEC_VP8E] = {
+       {
+               .codec_mode = RK3288_VPU_CODEC_VP8E,
                .init = rk3288_vpu_vp8e_init,
                .exit = rk3288_vpu_vp8e_exit,
                .irq = rk3288_vpu_enc_irq,
@@ -369,7 +321,8 @@ static const struct rockchip_vpu_codec_ops mode_ops[] = {
                .done = rk3288_vpu_vp8e_done,
                .reset = rk3288_vpu_enc_reset,
        },
-       [RK3288_VPU_CODEC_VP8D] = {
+       {
+               .codec_mode = RK3288_VPU_CODEC_VP8D,
                .init = rk3288_vpu_vp8d_init,
                .exit = rk3288_vpu_vp8d_exit,
                .irq = rk3288_vpu_dec_irq,
@@ -377,7 +330,8 @@ static const struct rockchip_vpu_codec_ops mode_ops[] = {
                .done = rockchip_vpu_run_done,
                .reset = rk3288_vpu_dec_reset,
        },
-       [RK3288_VPU_CODEC_H264D] = {
+       {
+               .codec_mode = RK3288_VPU_CODEC_H264D,
                .init = rk3288_vpu_h264d_init,
                .exit = rk3288_vpu_h264d_exit,
                .irq = rk3288_vpu_dec_irq,
@@ -395,13 +349,22 @@ void rockchip_vpu_run(struct rockchip_vpu_ctx *ctx)
 int rockchip_vpu_init(struct rockchip_vpu_ctx *ctx)
 {
        enum rockchip_vpu_codec_mode codec_mode;
+       int i;
 
        if (rockchip_vpu_ctx_is_encoder(ctx))
                codec_mode = ctx->vpu_dst_fmt->codec_mode; /* Encoder */
        else
                codec_mode = ctx->vpu_src_fmt->codec_mode; /* Decoder */
 
-       ctx->hw.codec_ops = &mode_ops[codec_mode];
+       for (i = 0; i < ARRAY_SIZE(mode_ops); i++) {
+               if (mode_ops[i].codec_mode == codec_mode) {
+                       ctx->hw.codec_ops = &mode_ops[i];
+                       break;
+               }
+       }
+
+       if (!ctx->hw.codec_ops)
+               return -1;
 
        return ctx->hw.codec_ops->init(ctx);
 }