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[] = {
[RK_VPU_MODE_JPEG_ENC] = {
.run = rk3288_vpu_jpeg_enc_run,
.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,
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_write_relaxed(vpu, ctx->bounce_size,
vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
......
......@@ -98,6 +98,8 @@ static const struct rockchip_vpu_codec_ops rk3399_vpu_codec_ops[] = {
[RK_VPU_MODE_JPEG_ENC] = {
.run = rk3399_vpu_jpeg_enc_run,
.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,
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_write_relaxed(vpu, ctx->bounce_size,
vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
......
......@@ -124,10 +124,7 @@ struct rockchip_vpu_dev {
* @jpeg_quality: User-specified JPEG compression quality.
*
* @codec_ops: Set of operations related to codec mode.
*
* @bounce_dma_addr: Bounce buffer bus address.
* @bounce_buf: Bounce buffer pointer.
* @bounce_size: Bounce buffer size.
* @jpeg_enc: JPEG-encoding context.
*/
struct rockchip_vpu_ctx {
struct rockchip_vpu_dev *dev;
......@@ -146,9 +143,10 @@ struct rockchip_vpu_ctx {
const struct rockchip_vpu_codec_ops *codec_ops;
dma_addr_t bounce_dma_addr;
void *bounce_buf;
size_t bounce_size;
/* Specific for particular codec modes. */
union {
struct rockchip_vpu_jpeg_enc_hw_ctx jpeg_enc;
};
};
/**
......
......@@ -63,10 +63,15 @@ static void rockchip_vpu_job_finish(struct rockchip_vpu_dev *vpu,
avail_size = vb2_plane_size(&dst->vb2_buf, 0) -
ctx->vpu_dst_fmt->header_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) +
ctx->vpu_dst_fmt->header_size,
ctx->bounce_buf, bytesused);
ctx->jpeg_enc.bounce_buffer.cpu, bytesused);
}
dst->vb2_buf.planes[0].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)
{
struct rockchip_vpu_ctx *ctx = vb2_get_drv_priv(q);
enum rockchip_vpu_codec_mode codec_mode;
int ret = 0;
if (V4L2_TYPE_IS_OUTPUT(q->type))
ctx->sequence_out = 0;
......@@ -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);
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)) {
ctx->bounce_size = ctx->dst_fmt.plane_fmt[0].sizeimage -
ctx->vpu_dst_fmt->header_size;
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;
if (!V4L2_TYPE_IS_OUTPUT(q->type))
if (ctx->codec_ops && ctx->codec_ops->init)
ret = ctx->codec_ops->init(ctx);
return ret;
}
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);
if (!V4L2_TYPE_IS_OUTPUT(q->type))
dma_free_attrs(ctx->dev->dev,
ctx->bounce_size,
ctx->bounce_buf,
ctx->bounce_dma_addr,
DMA_ATTR_ALLOC_SINGLE_PAGES);
if (ctx->codec_ops && ctx->codec_ops->exit)
ctx->codec_ops->exit(ctx);
/*
* The mem2mem framework calls v4l2_m2m_cancel_job before
......
......@@ -18,9 +18,33 @@ struct rockchip_vpu_ctx;
struct rockchip_vpu_buf;
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
*
* @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
* to indicate that a pair of buffers is ready and the hardware
* should be programmed and started.
......@@ -28,6 +52,8 @@ struct rockchip_vpu_variant;
* @reset: Reset the hardware in case of a timeout.
*/
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 (*done)(struct rockchip_vpu_ctx *ctx, enum vb2_buffer_state);
void (*reset)(struct rockchip_vpu_ctx *ctx);
......@@ -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 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_ */
......@@ -6,9 +6,11 @@
* Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
* Copyright (C) 2014 Philipp Zabel, Pengutronix
*/
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include "rockchip_vpu_jpeg.h"
#include "rockchip_vpu.h"
#define LUMA_QUANT_OFF 7
#define CHROMA_QUANT_OFF 72
......@@ -288,3 +290,30 @@ void rockchip_vpu_jpeg_header_assemble(struct rockchip_vpu_jpeg_ctx *ctx)
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