Skip to content
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/broadcom/bcm2711.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@
};

hevc_dec: codec@7eb10000 {
compatible = "brcm,bcm2711-hevc-dec", "raspberrypi,hevc-dec";
compatible = "brcm,bcm2711-hevc-dec";
reg = <0x0 0x7eb00000 0x10000>, /* HEVC */
<0x0 0x7eb10000 0x1000>; /* INTC */
reg-names = "hevc",
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@
};

hevc_dec: codec@800000 {
compatible = "brcm,bcm2712-hevc-dec", "raspberrypi,hevc-dec";
compatible = "brcm,bcm2712-hevc-dec", "brcm,bcm2711-hevc-dec";
reg = <0x10 0x00800000 0x0 0x10000>, /* HEVC */
<0x10 0x00840000 0x0 0x1000>; /* INTC */
reg-names = "hevc",
Expand Down
155 changes: 37 additions & 118 deletions drivers/media/platform/raspberrypi/hevc_dec/hevc_d.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include "hevc_d_video.h"
#include "hevc_d_hw.h"

int hevc_d_v4l2_debug;
module_param_named(debug, hevc_d_v4l2_debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level 0-2");

/*
* Default /dev/videoN node number.
* Deliberately avoid the very low numbers as these are often taken by webcams
Expand All @@ -34,54 +38,33 @@ static int video_nr = 19;
module_param(video_nr, int, 0644);
MODULE_PARM_DESC(video_nr, "decoder video device number");

static const struct hevc_d_control hevc_d_ctrls[] = {
static const struct v4l2_ctrl_config hevc_d_ctrls[] = {
{
.cfg = {
.id = V4L2_CID_STATELESS_HEVC_SPS,
.ops = &hevc_d_hevc_sps_ctrl_ops,
},
.required = false,
.id = V4L2_CID_STATELESS_HEVC_SPS,
.ops = &hevc_d_hevc_sps_ctrl_ops,
}, {
.cfg = {
.id = V4L2_CID_STATELESS_HEVC_PPS,
.ops = &hevc_d_hevc_pps_ctrl_ops,
},
.required = false,
.id = V4L2_CID_STATELESS_HEVC_PPS,
.ops = &hevc_d_hevc_pps_ctrl_ops,
}, {
.cfg = {
.id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
},
.required = false,
.id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX,
}, {
.cfg = {
.id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS,
},
.required = true,
.id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS,
}, {
.cfg = {
.name = "Slice param array",
.id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS,
.type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS,
.flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY,
.dims = { 0x1000 },
},
.required = true,
.name = "Slice param array",
.id = V4L2_CID_STATELESS_HEVC_SLICE_PARAMS,
.type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS,
.flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY,
.dims = { 0x1000 },
}, {
.cfg = {
.id = V4L2_CID_STATELESS_HEVC_DECODE_MODE,
.min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
.max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
.def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
},
.required = false,
.id = V4L2_CID_STATELESS_HEVC_DECODE_MODE,
.min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
.max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
.def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED,
}, {
.cfg = {
.id = V4L2_CID_STATELESS_HEVC_START_CODE,
.min = V4L2_STATELESS_HEVC_START_CODE_NONE,
.max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
.def = V4L2_STATELESS_HEVC_START_CODE_NONE,
},
.required = false,
.id = V4L2_CID_STATELESS_HEVC_START_CODE,
.min = V4L2_STATELESS_HEVC_START_CODE_NONE,
.max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B,
.def = V4L2_STATELESS_HEVC_START_CODE_NONE,
},
};

Expand Down Expand Up @@ -123,12 +106,11 @@ static int hevc_d_init_ctrls(struct hevc_d_dev *dev, struct hevc_d_ctx *ctx)
return -ENOMEM;

for (i = 0; i < HEVC_D_CTRLS_COUNT; i++) {
ctrl = v4l2_ctrl_new_custom(hdl, &hevc_d_ctrls[i].cfg,
ctx);
ctrl = v4l2_ctrl_new_custom(hdl, &hevc_d_ctrls[i], ctx);
if (hdl->error) {
v4l2_err(&dev->v4l2_dev,
"Failed to create new custom control id=%#x\n",
hevc_d_ctrls[i].cfg.id);
hevc_d_ctrls[i].id);

v4l2_ctrl_handler_free(hdl);
kfree(ctx->ctrls);
Expand All @@ -144,69 +126,6 @@ static int hevc_d_init_ctrls(struct hevc_d_dev *dev, struct hevc_d_ctx *ctx)
return 0;
}

static int hevc_d_request_validate(struct media_request *req)
{
struct media_request_object *obj;
struct v4l2_ctrl_handler *parent_hdl, *hdl;
struct hevc_d_ctx *ctx = NULL;
struct v4l2_ctrl *ctrl_test;
unsigned int count;
unsigned int i;

list_for_each_entry(obj, &req->objects, list) {
struct vb2_buffer *vb;

if (vb2_request_object_is_buffer(obj)) {
vb = container_of(obj, struct vb2_buffer, req_obj);
ctx = vb2_get_drv_priv(vb->vb2_queue);

break;
}
}

if (!ctx)
return -ENOENT;

count = vb2_request_buffer_cnt(req);
if (!count) {
v4l2_info(&ctx->dev->v4l2_dev,
"No buffer was provided with the request\n");
return -ENOENT;
} else if (count > 1) {
v4l2_info(&ctx->dev->v4l2_dev,
"More than one buffer was provided with the request\n");
return -EINVAL;
}

parent_hdl = &ctx->hdl;

hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
if (!hdl) {
v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control(s)\n");
return -ENOENT;
}

for (i = 0; i < HEVC_D_CTRLS_COUNT; i++) {
if (!hevc_d_ctrls[i].required)
continue;

ctrl_test =
v4l2_ctrl_request_hdl_ctrl_find(hdl,
hevc_d_ctrls[i].cfg.id);
if (!ctrl_test) {
v4l2_info(&ctx->dev->v4l2_dev,
"Missing required codec control %d: id=%#x\n",
i, hevc_d_ctrls[i].cfg.id);
v4l2_ctrl_request_hdl_put(hdl);
return -ENOENT;
}
}

v4l2_ctrl_request_hdl_put(hdl);

return vb2_request_validate(req);
}

static int hevc_d_open(struct file *file)
{
struct hevc_d_dev *dev = video_drvdata(file);
Expand All @@ -229,17 +148,17 @@ static int hevc_d_open(struct file *file)
file->private_data = &ctx->fh;
ctx->dev = dev;

ret = hevc_d_init_ctrls(dev, ctx);
if (ret)
goto err_free;

ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
&hevc_d_queue_init);
if (IS_ERR(ctx->fh.m2m_ctx)) {
ret = PTR_ERR(ctx->fh.m2m_ctx);
goto err_ctrls;
goto err_free;
}

ret = hevc_d_init_ctrls(dev, ctx);
if (ret)
goto err_ctx;

/* The only bit of format info that we can guess now is H265 src
* Everything else we need more info for
*/
Expand All @@ -251,9 +170,8 @@ static int hevc_d_open(struct file *file)

return 0;

err_ctrls:
v4l2_ctrl_handler_free(&ctx->hdl);
kfree(ctx->ctrls);
err_ctx:
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
err_free:
mutex_destroy(&ctx->ctx_mutex);
kfree(ctx);
Expand All @@ -272,11 +190,12 @@ static int hevc_d_release(struct file *file)
mutex_lock(&dev->dev_mutex);

v4l2_fh_del(&ctx->fh);
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);

v4l2_ctrl_handler_free(&ctx->hdl);
kfree(ctx->ctrls);

v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);

v4l2_fh_exit(&ctx->fh);
mutex_destroy(&ctx->ctx_mutex);

Expand Down Expand Up @@ -317,7 +236,7 @@ static const struct v4l2_m2m_ops hevc_d_m2m_ops = {
};

static const struct media_device_ops hevc_d_m2m_media_ops = {
.req_validate = hevc_d_request_validate,
.req_validate = vb2_request_validate,
.req_queue = hevc_d_media_req_queue,
};

Expand Down Expand Up @@ -439,7 +358,7 @@ static void hevc_d_remove(struct platform_device *pdev)
}

static const struct of_device_id hevc_d_dt_match[] = {
{ .compatible = "raspberrypi,hevc-dec", },
{ .compatible = "brcm,bcm2711-hevc-dec", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, hevc_d_dt_match);
Expand Down
43 changes: 23 additions & 20 deletions drivers/media/platform/raspberrypi/hevc_dec/hevc_d.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,36 @@
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>

#define HEVC_D_DEC_ENV_COUNT 6
/*
* Q sizes of 3 give one entry being prepared, one waiting and
* one processing. Testing shows no advantage to greater Q depths
*/

/*
* Max processing Q size Phase 0 -> Phase 1
* This is per open context
*/
#define HEVC_D_P1BUF_COUNT 3
/*
* Max processing Q size Phase 1 -> Phase 2
* This is per device
*/
#define HEVC_D_P2BUF_COUNT 3
/*
* Number of decode environments a context has
* There is no independent flow control on this number so it must be
* capable of holding P1 + P2 entries.
*/
#define HEVC_D_DEC_ENV_COUNT (HEVC_D_P1BUF_COUNT + HEVC_D_P2BUF_COUNT)

#define HEVC_D_NAME "rpi-hevc-dec"

#define HEVC_D_CAPABILITY_UNTILED BIT(0)
#define HEVC_D_CAPABILITY_H265_DEC BIT(1)

#define HEVC_D_QUIRK_NO_DMA_OFFSET BIT(0)

enum hevc_d_irq_status {
HEVC_D_IRQ_NONE,
HEVC_D_IRQ_ERROR,
HEVC_D_IRQ_OK,
};

struct hevc_d_control {
struct v4l2_ctrl_config cfg;
unsigned char required:1;
};

struct hevc_d_h265_run {
u32 slice_ents;
const struct v4l2_ctrl_hevc_sps *sps;
Expand Down Expand Up @@ -88,9 +96,6 @@ struct hevc_d_ctx {
struct v4l2_pix_format_mplane dst_fmt;
int dst_fmt_set;

int src_stream_on;
int dst_stream_on;

/*
* fatal_err is set if an error has occurred s.t. decode cannot
* continue (such as running out of CMA)
Expand Down Expand Up @@ -133,12 +138,6 @@ struct hevc_d_ctx {
unsigned int colmv_picsize;
};

struct hevc_d_variant {
unsigned int capabilities;
unsigned int quirks;
unsigned int mod_rate;
};

struct hevc_d_hw_irq_ent;

#define HEVC_D_ICTL_ENABLE_UNLIMITED (-1)
Expand Down Expand Up @@ -183,6 +182,10 @@ struct hevc_d_dev {
struct hevc_d_hw_irq_ctrl ic_active2;
};

extern int hevc_d_v4l2_debug;
#define hevc_d_dbg(level, dev, fmt, arg...)\
v4l2_dbg((level), hevc_d_v4l2_debug, (dev), fmt, ## arg)

struct v4l2_ctrl *hevc_d_find_ctrl(struct hevc_d_ctx *ctx, u32 id);
void *hevc_d_find_control_data(struct hevc_d_ctx *ctx, u32 id);

Expand Down
Loading
Loading