{
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;
* 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;
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;
}
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");
"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");
"Rockchip VPU decoder registered as /vpu/video%d\n",
vfd->num);
+no_decoder:
vpu_debug_leave();
return 0;
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 */ }
};
#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)
{
.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,
},
};
#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).
* (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.
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;
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,
.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];
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;
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);
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))
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)
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];
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;
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;
{
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;
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;
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);
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;
},
};
-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)
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;
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);
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)
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)
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];
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;
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;
{
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;
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;
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);
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 = {
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);
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;
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;
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)
#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()
* @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 *);
* 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();
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);
}
/*
*
* 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;
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;
}
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,
.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,
.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,
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);
}