summaryrefslogtreecommitdiff
path: root/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c')
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
index 4df16f59fb97..8395c4d48dd0 100644
--- a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
@@ -35,18 +35,23 @@
static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
- struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
+ u32 overfill_r, overfill_b;
u32 reg;
/*
- * The pix fmt width/height are already macroblock aligned
- * by .vidioc_s_fmt_vid_cap_mplane() callback
+ * The format width and height are already macroblock aligned
+ * by .vidioc_s_fmt_vid_cap_mplane() callback. Destination
+ * format width and height can be further modified by
+ * .vidioc_s_selection(), and the width is 4-aligned.
*/
- reg = VEPU_REG_IN_IMG_CTRL_ROW_LEN(pix_fmt->width);
+ overfill_r = ctx->src_fmt.width - ctx->dst_fmt.width;
+ overfill_b = ctx->src_fmt.height - ctx->dst_fmt.height;
+
+ reg = VEPU_REG_IN_IMG_CTRL_ROW_LEN(ctx->src_fmt.width);
vepu_write_relaxed(vpu, reg, VEPU_REG_INPUT_LUMA_INFO);
- reg = VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(0) |
- VEPU_REG_IN_IMG_CTRL_OVRFLB(0);
+ reg = VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r / 4) |
+ VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b);
/*
* This register controls the input crop, as the offset
* from the right/bottom within the last macroblock. The offset from the
@@ -61,17 +66,23 @@ static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
static void rockchip_vpu2_jpeg_enc_set_buffers(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
- struct vb2_buffer *src_buf)
+ struct vb2_buffer *src_buf,
+ struct vb2_buffer *dst_buf)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
dma_addr_t src[3];
+ u32 size_left;
+
+ size_left = vb2_plane_size(dst_buf, 0) - ctx->vpu_dst_fmt->header_size;
+ if (WARN_ON(vb2_plane_size(dst_buf, 0) < ctx->vpu_dst_fmt->header_size))
+ size_left = 0;
WARN_ON(pix_fmt->num_planes > 3);
- vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.dma,
+ vepu_write_relaxed(vpu, vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
+ ctx->vpu_dst_fmt->header_size,
VEPU_REG_ADDR_OUTPUT_STREAM);
- vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
- VEPU_REG_STR_BUF_LIMIT);
+ vepu_write_relaxed(vpu, size_left, VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
@@ -132,6 +143,9 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
memset(&jpeg_ctx, 0, sizeof(jpeg_ctx));
jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
+ if (!jpeg_ctx.buffer)
+ return -ENOMEM;
+
jpeg_ctx.width = ctx->dst_fmt.width;
jpeg_ctx.height = ctx->dst_fmt.height;
jpeg_ctx.quality = ctx->jpeg_quality;
@@ -142,7 +156,8 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
VEPU_REG_ENCODE_START);
rockchip_vpu2_set_src_img_ctrl(vpu, ctx);
- rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
+ rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf,
+ &dst_buf->vb2_buf);
rockchip_vpu2_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable,
jpeg_ctx.hw_chroma_qtable);
@@ -177,13 +192,6 @@ void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx)
u32 bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8;
struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx);
- /*
- * TODO: Rework the JPEG encoder to eliminate the need
- * for a bounce buffer.
- */
- memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) +
- ctx->vpu_dst_fmt->header_size,
- ctx->jpeg_enc.bounce_buffer.cpu, bytesused);
vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
ctx->vpu_dst_fmt->header_size + bytesused);
}