From: Jeffy Chen Date: Thu, 2 Jun 2016 07:05:52 +0000 (+0800) Subject: CHROMIUM: [media] rockchip-vpu: reconstructs for futher chips X-Git-Tag: firefly_0821_release~2287 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=89b2150201acc12fdc0b5c1b1d68f6c41f87941e;p=firefly-linux-kernel-4.4.55.git CHROMIUM: [media] rockchip-vpu: reconstructs for futher chips Change-Id: Ia88f45b37a1af829723e6b8cb9d8ff3cb5f54530 Signed-off-by: Jeffy Chen Signed-off-by: Yakir Yang --- diff --git a/drivers/media/platform/rockchip-vpu/rockchip_vpu.c b/drivers/media/platform/rockchip-vpu/rockchip_vpu.c index 4b0b184a6b8e..e7bb63562e2f 100644 --- a/drivers/media/platform/rockchip-vpu/rockchip_vpu.c +++ b/drivers/media/platform/rockchip-vpu/rockchip_vpu.c @@ -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, }, }; diff --git a/drivers/media/platform/rockchip-vpu/rockchip_vpu_common.h b/drivers/media/platform/rockchip-vpu/rockchip_vpu_common.h index 71b805b80c0a..2f5ccf0055ac 100644 --- a/drivers/media/platform/rockchip-vpu/rockchip_vpu_common.h +++ b/drivers/media/platform/rockchip-vpu/rockchip_vpu_common.h @@ -50,24 +50,48 @@ #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, diff --git a/drivers/media/platform/rockchip-vpu/rockchip_vpu_dec.c b/drivers/media/platform/rockchip-vpu/rockchip_vpu_dec.c index 7e7e7242b886..e1e1452de6f7 100644 --- a/drivers/media/platform/rockchip-vpu/rockchip_vpu_dec.c +++ b/drivers/media/platform/rockchip-vpu/rockchip_vpu_dec.c @@ -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; diff --git a/drivers/media/platform/rockchip-vpu/rockchip_vpu_enc.c b/drivers/media/platform/rockchip-vpu/rockchip_vpu_enc.c index 0a10392a0fee..dd5c1770284a 100644 --- a/drivers/media/platform/rockchip-vpu/rockchip_vpu_enc.c +++ b/drivers/media/platform/rockchip-vpu/rockchip_vpu_enc.c @@ -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) diff --git a/drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.c b/drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.c index 3959d9f2c957..d97ac7f90a8b 100644 --- a/drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.c +++ b/drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.c @@ -38,37 +38,11 @@ #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); }