Commit 9d4e1f74 authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by Mauro Carvalho Chehab

media: rockchip/vpu: Cleanup JPEG bounce buffer management

In order to make the code more generic, introduce a pair of start/stop
codec operations, and use them to allocate and release the JPEG bounce
buffer.
Signed-off-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 92cd4307
...@@ -98,6 +98,8 @@ static const struct rockchip_vpu_codec_ops rk3288_vpu_codec_ops[] = { ...@@ -98,6 +98,8 @@ static const struct rockchip_vpu_codec_ops rk3288_vpu_codec_ops[] = {
[RK_VPU_MODE_JPEG_ENC] = { [RK_VPU_MODE_JPEG_ENC] = {
.run = rk3288_vpu_jpeg_enc_run, .run = rk3288_vpu_jpeg_enc_run,
.reset = rk3288_vpu_enc_reset, .reset = rk3288_vpu_enc_reset,
.init = rockchip_vpu_jpeg_enc_init,
.exit = rockchip_vpu_jpeg_enc_exit,
}, },
}; };
......
...@@ -37,9 +37,9 @@ static void rk3288_vpu_jpeg_enc_set_buffers(struct rockchip_vpu_dev *vpu, ...@@ -37,9 +37,9 @@ static void rk3288_vpu_jpeg_enc_set_buffers(struct rockchip_vpu_dev *vpu,
WARN_ON(pix_fmt->num_planes > 3); WARN_ON(pix_fmt->num_planes > 3);
vepu_write_relaxed(vpu, ctx->bounce_dma_addr, vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.dma,
VEPU_REG_ADDR_OUTPUT_STREAM); VEPU_REG_ADDR_OUTPUT_STREAM);
vepu_write_relaxed(vpu, ctx->bounce_size, vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
VEPU_REG_STR_BUF_LIMIT); VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) { if (pix_fmt->num_planes == 1) {
......
...@@ -98,6 +98,8 @@ static const struct rockchip_vpu_codec_ops rk3399_vpu_codec_ops[] = { ...@@ -98,6 +98,8 @@ static const struct rockchip_vpu_codec_ops rk3399_vpu_codec_ops[] = {
[RK_VPU_MODE_JPEG_ENC] = { [RK_VPU_MODE_JPEG_ENC] = {
.run = rk3399_vpu_jpeg_enc_run, .run = rk3399_vpu_jpeg_enc_run,
.reset = rk3399_vpu_enc_reset, .reset = rk3399_vpu_enc_reset,
.init = rockchip_vpu_jpeg_enc_init,
.exit = rockchip_vpu_jpeg_enc_exit,
}, },
}; };
......
...@@ -69,9 +69,9 @@ static void rk3399_vpu_jpeg_enc_set_buffers(struct rockchip_vpu_dev *vpu, ...@@ -69,9 +69,9 @@ static void rk3399_vpu_jpeg_enc_set_buffers(struct rockchip_vpu_dev *vpu,
WARN_ON(pix_fmt->num_planes > 3); WARN_ON(pix_fmt->num_planes > 3);
vepu_write_relaxed(vpu, ctx->bounce_dma_addr, vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.dma,
VEPU_REG_ADDR_OUTPUT_STREAM); VEPU_REG_ADDR_OUTPUT_STREAM);
vepu_write_relaxed(vpu, ctx->bounce_size, vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
VEPU_REG_STR_BUF_LIMIT); VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) { if (pix_fmt->num_planes == 1) {
......
...@@ -124,10 +124,7 @@ struct rockchip_vpu_dev { ...@@ -124,10 +124,7 @@ struct rockchip_vpu_dev {
* @jpeg_quality: User-specified JPEG compression quality. * @jpeg_quality: User-specified JPEG compression quality.
* *
* @codec_ops: Set of operations related to codec mode. * @codec_ops: Set of operations related to codec mode.
* * @jpeg_enc: JPEG-encoding context.
* @bounce_dma_addr: Bounce buffer bus address.
* @bounce_buf: Bounce buffer pointer.
* @bounce_size: Bounce buffer size.
*/ */
struct rockchip_vpu_ctx { struct rockchip_vpu_ctx {
struct rockchip_vpu_dev *dev; struct rockchip_vpu_dev *dev;
...@@ -146,9 +143,10 @@ struct rockchip_vpu_ctx { ...@@ -146,9 +143,10 @@ struct rockchip_vpu_ctx {
const struct rockchip_vpu_codec_ops *codec_ops; const struct rockchip_vpu_codec_ops *codec_ops;
dma_addr_t bounce_dma_addr; /* Specific for particular codec modes. */
void *bounce_buf; union {
size_t bounce_size; struct rockchip_vpu_jpeg_enc_hw_ctx jpeg_enc;
};
}; };
/** /**
......
...@@ -63,10 +63,15 @@ static void rockchip_vpu_job_finish(struct rockchip_vpu_dev *vpu, ...@@ -63,10 +63,15 @@ static void rockchip_vpu_job_finish(struct rockchip_vpu_dev *vpu,
avail_size = vb2_plane_size(&dst->vb2_buf, 0) - avail_size = vb2_plane_size(&dst->vb2_buf, 0) -
ctx->vpu_dst_fmt->header_size; ctx->vpu_dst_fmt->header_size;
if (bytesused <= avail_size) { if (bytesused <= avail_size) {
if (ctx->bounce_buf) { /*
* The bounce buffer is only for the JPEG encoder.
* TODO: Rework the JPEG encoder to eliminate the need
* for a bounce buffer.
*/
if (ctx->jpeg_enc.bounce_buffer.cpu) {
memcpy(vb2_plane_vaddr(&dst->vb2_buf, 0) + memcpy(vb2_plane_vaddr(&dst->vb2_buf, 0) +
ctx->vpu_dst_fmt->header_size, ctx->vpu_dst_fmt->header_size,
ctx->bounce_buf, bytesused); ctx->jpeg_enc.bounce_buffer.cpu, bytesused);
} }
dst->vb2_buf.planes[0].bytesused = dst->vb2_buf.planes[0].bytesused =
ctx->vpu_dst_fmt->header_size + bytesused; ctx->vpu_dst_fmt->header_size + bytesused;
......
...@@ -515,6 +515,7 @@ static int rockchip_vpu_start_streaming(struct vb2_queue *q, unsigned int count) ...@@ -515,6 +515,7 @@ static int rockchip_vpu_start_streaming(struct vb2_queue *q, unsigned int count)
{ {
struct rockchip_vpu_ctx *ctx = vb2_get_drv_priv(q); struct rockchip_vpu_ctx *ctx = vb2_get_drv_priv(q);
enum rockchip_vpu_codec_mode codec_mode; enum rockchip_vpu_codec_mode codec_mode;
int ret = 0;
if (V4L2_TYPE_IS_OUTPUT(q->type)) if (V4L2_TYPE_IS_OUTPUT(q->type))
ctx->sequence_out = 0; ctx->sequence_out = 0;
...@@ -527,17 +528,10 @@ static int rockchip_vpu_start_streaming(struct vb2_queue *q, unsigned int count) ...@@ -527,17 +528,10 @@ static int rockchip_vpu_start_streaming(struct vb2_queue *q, unsigned int count)
vpu_debug(4, "Codec mode = %d\n", codec_mode); vpu_debug(4, "Codec mode = %d\n", codec_mode);
ctx->codec_ops = &ctx->dev->variant->codec_ops[codec_mode]; ctx->codec_ops = &ctx->dev->variant->codec_ops[codec_mode];
/* A bounce buffer is needed for the JPEG payload */ if (!V4L2_TYPE_IS_OUTPUT(q->type))
if (!V4L2_TYPE_IS_OUTPUT(q->type)) { if (ctx->codec_ops && ctx->codec_ops->init)
ctx->bounce_size = ctx->dst_fmt.plane_fmt[0].sizeimage - ret = ctx->codec_ops->init(ctx);
ctx->vpu_dst_fmt->header_size; return ret;
ctx->bounce_buf = dma_alloc_attrs(ctx->dev->dev,
ctx->bounce_size,
&ctx->bounce_dma_addr,
GFP_KERNEL,
DMA_ATTR_ALLOC_SINGLE_PAGES);
}
return 0;
} }
static void rockchip_vpu_stop_streaming(struct vb2_queue *q) static void rockchip_vpu_stop_streaming(struct vb2_queue *q)
...@@ -545,11 +539,8 @@ static void rockchip_vpu_stop_streaming(struct vb2_queue *q) ...@@ -545,11 +539,8 @@ static void rockchip_vpu_stop_streaming(struct vb2_queue *q)
struct rockchip_vpu_ctx *ctx = vb2_get_drv_priv(q); struct rockchip_vpu_ctx *ctx = vb2_get_drv_priv(q);
if (!V4L2_TYPE_IS_OUTPUT(q->type)) if (!V4L2_TYPE_IS_OUTPUT(q->type))
dma_free_attrs(ctx->dev->dev, if (ctx->codec_ops && ctx->codec_ops->exit)
ctx->bounce_size, ctx->codec_ops->exit(ctx);
ctx->bounce_buf,
ctx->bounce_dma_addr,
DMA_ATTR_ALLOC_SINGLE_PAGES);
/* /*
* The mem2mem framework calls v4l2_m2m_cancel_job before * The mem2mem framework calls v4l2_m2m_cancel_job before
......
...@@ -18,9 +18,33 @@ struct rockchip_vpu_ctx; ...@@ -18,9 +18,33 @@ struct rockchip_vpu_ctx;
struct rockchip_vpu_buf; struct rockchip_vpu_buf;
struct rockchip_vpu_variant; struct rockchip_vpu_variant;
/**
* struct rockchip_vpu_aux_buf - auxiliary DMA buffer for hardware data
* @cpu: CPU pointer to the buffer.
* @dma: DMA address of the buffer.
* @size: Size of the buffer.
*/
struct rockchip_vpu_aux_buf {
void *cpu;
dma_addr_t dma;
size_t size;
};
/**
* struct rockchip_vpu_jpeg_enc_hw_ctx
* @bounce_buffer: Bounce buffer
*/
struct rockchip_vpu_jpeg_enc_hw_ctx {
struct rockchip_vpu_aux_buf bounce_buffer;
};
/** /**
* struct rockchip_vpu_codec_ops - codec mode specific operations * struct rockchip_vpu_codec_ops - codec mode specific operations
* *
* @init: If needed, can be used for initialization.
* Optional and called from process context.
* @exit: If needed, can be used to undo the .init phase.
* Optional and called from process context.
* @run: Start single {en,de)coding job. Called from atomic context * @run: Start single {en,de)coding job. Called from atomic context
* to indicate that a pair of buffers is ready and the hardware * to indicate that a pair of buffers is ready and the hardware
* should be programmed and started. * should be programmed and started.
...@@ -28,6 +52,8 @@ struct rockchip_vpu_variant; ...@@ -28,6 +52,8 @@ struct rockchip_vpu_variant;
* @reset: Reset the hardware in case of a timeout. * @reset: Reset the hardware in case of a timeout.
*/ */
struct rockchip_vpu_codec_ops { struct rockchip_vpu_codec_ops {
int (*init)(struct rockchip_vpu_ctx *ctx);
void (*exit)(struct rockchip_vpu_ctx *ctx);
void (*run)(struct rockchip_vpu_ctx *ctx); void (*run)(struct rockchip_vpu_ctx *ctx);
void (*done)(struct rockchip_vpu_ctx *ctx, enum vb2_buffer_state); void (*done)(struct rockchip_vpu_ctx *ctx, enum vb2_buffer_state);
void (*reset)(struct rockchip_vpu_ctx *ctx); void (*reset)(struct rockchip_vpu_ctx *ctx);
...@@ -54,5 +80,7 @@ void rockchip_vpu_irq_done(struct rockchip_vpu_dev *vpu, ...@@ -54,5 +80,7 @@ void rockchip_vpu_irq_done(struct rockchip_vpu_dev *vpu,
void rk3288_vpu_jpeg_enc_run(struct rockchip_vpu_ctx *ctx); void rk3288_vpu_jpeg_enc_run(struct rockchip_vpu_ctx *ctx);
void rk3399_vpu_jpeg_enc_run(struct rockchip_vpu_ctx *ctx); void rk3399_vpu_jpeg_enc_run(struct rockchip_vpu_ctx *ctx);
int rockchip_vpu_jpeg_enc_init(struct rockchip_vpu_ctx *ctx);
void rockchip_vpu_jpeg_enc_exit(struct rockchip_vpu_ctx *ctx);
#endif /* ROCKCHIP_VPU_HW_H_ */ #endif /* ROCKCHIP_VPU_HW_H_ */
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
* Copyright (C) Jean-Francois Moine (http://moinejf.free.fr) * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
* Copyright (C) 2014 Philipp Zabel, Pengutronix * Copyright (C) 2014 Philipp Zabel, Pengutronix
*/ */
#include <linux/dma-mapping.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include "rockchip_vpu_jpeg.h" #include "rockchip_vpu_jpeg.h"
#include "rockchip_vpu.h"
#define LUMA_QUANT_OFF 7 #define LUMA_QUANT_OFF 7
#define CHROMA_QUANT_OFF 72 #define CHROMA_QUANT_OFF 72
...@@ -288,3 +290,30 @@ void rockchip_vpu_jpeg_header_assemble(struct rockchip_vpu_jpeg_ctx *ctx) ...@@ -288,3 +290,30 @@ void rockchip_vpu_jpeg_header_assemble(struct rockchip_vpu_jpeg_ctx *ctx)
jpeg_set_quality(buf, ctx->quality); jpeg_set_quality(buf, ctx->quality);
} }
int rockchip_vpu_jpeg_enc_init(struct rockchip_vpu_ctx *ctx)
{
ctx->jpeg_enc.bounce_buffer.size =
ctx->dst_fmt.plane_fmt[0].sizeimage -
ctx->vpu_dst_fmt->header_size;
ctx->jpeg_enc.bounce_buffer.cpu =
dma_alloc_attrs(ctx->dev->dev,
ctx->jpeg_enc.bounce_buffer.size,
&ctx->jpeg_enc.bounce_buffer.dma,
GFP_KERNEL,
DMA_ATTR_ALLOC_SINGLE_PAGES);
if (!ctx->jpeg_enc.bounce_buffer.cpu)
return -ENOMEM;
return 0;
}
void rockchip_vpu_jpeg_enc_exit(struct rockchip_vpu_ctx *ctx)
{
dma_free_attrs(ctx->dev->dev,
ctx->jpeg_enc.bounce_buffer.size,
ctx->jpeg_enc.bounce_buffer.cpu,
ctx->jpeg_enc.bounce_buffer.dma,
DMA_ATTR_ALLOC_SINGLE_PAGES);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment