mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-22 02:36:35 -04:00
media: iris: Add HEVC and VP9 formats for decoder
Extend the decoder driver's supported formats to include HEVC (H.265) and VP9. This change updates the format enumeration (VIDIOC_ENUM_FMT) and allows setting these formats via VIDIOC_S_FMT. Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Acked-by: Vikash Garodia <quic_vgarodia@quicinc.com> Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-QRD Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com> Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # on sa8775p-ride Signed-off-by: Bryan O'Donoghue <bod@kernel.org> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
This commit is contained in:
committed by
Hans Verkuil
parent
c7501fa5fb
commit
fde6161d91
@@ -88,16 +88,29 @@ static int iris_hfi_gen1_sys_pc_prep(struct iris_core *core)
|
|||||||
static int iris_hfi_gen1_session_open(struct iris_inst *inst)
|
static int iris_hfi_gen1_session_open(struct iris_inst *inst)
|
||||||
{
|
{
|
||||||
struct hfi_session_open_pkt packet;
|
struct hfi_session_open_pkt packet;
|
||||||
|
u32 codec = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (inst->state != IRIS_INST_DEINIT)
|
if (inst->state != IRIS_INST_DEINIT)
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
|
|
||||||
|
switch (inst->codec) {
|
||||||
|
case V4L2_PIX_FMT_H264:
|
||||||
|
codec = HFI_VIDEO_CODEC_H264;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_HEVC:
|
||||||
|
codec = HFI_VIDEO_CODEC_HEVC;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_VP9:
|
||||||
|
codec = HFI_VIDEO_CODEC_VP9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
|
packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
|
||||||
packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
|
packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
|
||||||
packet.shdr.session_id = inst->session_id;
|
packet.shdr.session_id = inst->session_id;
|
||||||
packet.session_domain = HFI_SESSION_TYPE_DEC;
|
packet.session_domain = HFI_SESSION_TYPE_DEC;
|
||||||
packet.session_codec = HFI_VIDEO_CODEC_H264;
|
packet.session_codec = codec;
|
||||||
|
|
||||||
reinit_completion(&inst->completion);
|
reinit_completion(&inst->completion);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#define HFI_SESSION_TYPE_DEC 2
|
#define HFI_SESSION_TYPE_DEC 2
|
||||||
|
|
||||||
#define HFI_VIDEO_CODEC_H264 0x00000002
|
#define HFI_VIDEO_CODEC_H264 0x00000002
|
||||||
|
#define HFI_VIDEO_CODEC_HEVC 0x00002000
|
||||||
|
#define HFI_VIDEO_CODEC_VP9 0x00004000
|
||||||
|
|
||||||
#define HFI_ERR_NONE 0x0
|
#define HFI_ERR_NONE 0x0
|
||||||
|
|
||||||
|
|||||||
@@ -416,7 +416,19 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p
|
|||||||
static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
|
static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
|
||||||
{
|
{
|
||||||
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
|
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
|
||||||
u32 codec = HFI_CODEC_DECODE_AVC;
|
u32 codec = 0;
|
||||||
|
|
||||||
|
switch (inst->codec) {
|
||||||
|
case V4L2_PIX_FMT_H264:
|
||||||
|
codec = HFI_CODEC_DECODE_AVC;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_HEVC:
|
||||||
|
codec = HFI_CODEC_DECODE_HEVC;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_VP9:
|
||||||
|
codec = HFI_CODEC_DECODE_VP9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
iris_hfi_gen2_packet_session_property(inst,
|
iris_hfi_gen2_packet_session_property(inst,
|
||||||
HFI_PROP_CODEC,
|
HFI_PROP_CODEC,
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ enum hfi_color_format {
|
|||||||
enum hfi_codec_type {
|
enum hfi_codec_type {
|
||||||
HFI_CODEC_DECODE_AVC = 1,
|
HFI_CODEC_DECODE_AVC = 1,
|
||||||
HFI_CODEC_ENCODE_AVC = 2,
|
HFI_CODEC_ENCODE_AVC = 2,
|
||||||
|
HFI_CODEC_DECODE_HEVC = 3,
|
||||||
|
HFI_CODEC_ENCODE_HEVC = 4,
|
||||||
|
HFI_CODEC_DECODE_VP9 = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hfi_picture_type {
|
enum hfi_picture_type {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
* @sequence_out: a sequence counter for output queue
|
* @sequence_out: a sequence counter for output queue
|
||||||
* @tss: timestamp metadata
|
* @tss: timestamp metadata
|
||||||
* @metadata_idx: index for metadata buffer
|
* @metadata_idx: index for metadata buffer
|
||||||
|
* @codec: codec type
|
||||||
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
|
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -75,6 +76,7 @@ struct iris_inst {
|
|||||||
u32 sequence_out;
|
u32 sequence_out;
|
||||||
struct iris_ts_metadata tss[VIDEO_MAX_FRAME];
|
struct iris_ts_metadata tss[VIDEO_MAX_FRAME];
|
||||||
u32 metadata_idx;
|
u32 metadata_idx;
|
||||||
|
u32 codec;
|
||||||
bool last_buffer_dequeued;
|
bool last_buffer_dequeued;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ int iris_vdec_inst_init(struct iris_inst *inst)
|
|||||||
f->fmt.pix_mp.width = DEFAULT_WIDTH;
|
f->fmt.pix_mp.width = DEFAULT_WIDTH;
|
||||||
f->fmt.pix_mp.height = DEFAULT_HEIGHT;
|
f->fmt.pix_mp.height = DEFAULT_HEIGHT;
|
||||||
f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
|
f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
|
||||||
|
inst->codec = f->fmt.pix_mp.pixelformat;
|
||||||
f->fmt.pix_mp.num_planes = 1;
|
f->fmt.pix_mp.num_planes = 1;
|
||||||
f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
|
f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
|
||||||
f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
|
f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
|
||||||
@@ -67,14 +68,67 @@ void iris_vdec_inst_deinit(struct iris_inst *inst)
|
|||||||
kfree(inst->fmt_src);
|
kfree(inst->fmt_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct iris_fmt iris_vdec_formats[] = {
|
||||||
|
[IRIS_FMT_H264] = {
|
||||||
|
.pixfmt = V4L2_PIX_FMT_H264,
|
||||||
|
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||||
|
},
|
||||||
|
[IRIS_FMT_HEVC] = {
|
||||||
|
.pixfmt = V4L2_PIX_FMT_HEVC,
|
||||||
|
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||||
|
},
|
||||||
|
[IRIS_FMT_VP9] = {
|
||||||
|
.pixfmt = V4L2_PIX_FMT_VP9,
|
||||||
|
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iris_fmt *
|
||||||
|
find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
|
||||||
|
{
|
||||||
|
unsigned int size = ARRAY_SIZE(iris_vdec_formats);
|
||||||
|
const struct iris_fmt *fmt = iris_vdec_formats;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if (fmt[i].pixfmt == pixfmt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == size || fmt[i].type != type)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &fmt[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iris_fmt *
|
||||||
|
find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
|
||||||
|
{
|
||||||
|
const struct iris_fmt *fmt = iris_vdec_formats;
|
||||||
|
unsigned int size = ARRAY_SIZE(iris_vdec_formats);
|
||||||
|
|
||||||
|
if (index >= size || fmt[index].type != type)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &fmt[index];
|
||||||
|
}
|
||||||
|
|
||||||
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
|
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
|
||||||
{
|
{
|
||||||
|
const struct iris_fmt *fmt;
|
||||||
|
|
||||||
switch (f->type) {
|
switch (f->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
||||||
f->pixelformat = V4L2_PIX_FMT_H264;
|
fmt = find_format_by_index(inst, f->index, f->type);
|
||||||
|
if (!fmt)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
f->pixelformat = fmt->pixfmt;
|
||||||
f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_DYN_RESOLUTION;
|
f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_DYN_RESOLUTION;
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
||||||
|
if (f->index)
|
||||||
|
return -EINVAL;
|
||||||
f->pixelformat = V4L2_PIX_FMT_NV12;
|
f->pixelformat = V4L2_PIX_FMT_NV12;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -88,13 +142,15 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
|
|||||||
{
|
{
|
||||||
struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
|
struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
|
||||||
struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
|
struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
|
||||||
|
const struct iris_fmt *fmt;
|
||||||
struct v4l2_format *f_inst;
|
struct v4l2_format *f_inst;
|
||||||
struct vb2_queue *src_q;
|
struct vb2_queue *src_q;
|
||||||
|
|
||||||
memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
|
memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
|
||||||
|
fmt = find_format(inst, pixmp->pixelformat, f->type);
|
||||||
switch (f->type) {
|
switch (f->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
||||||
if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) {
|
if (!fmt) {
|
||||||
f_inst = inst->fmt_src;
|
f_inst = inst->fmt_src;
|
||||||
f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
|
f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
|
||||||
f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
|
f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
|
||||||
@@ -102,7 +158,7 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
||||||
if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) {
|
if (!fmt) {
|
||||||
f_inst = inst->fmt_dst;
|
f_inst = inst->fmt_dst;
|
||||||
f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
|
f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
|
||||||
f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
|
f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
|
||||||
@@ -145,13 +201,14 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
|
|||||||
|
|
||||||
switch (f->type) {
|
switch (f->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
||||||
if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264)
|
if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
fmt = inst->fmt_src;
|
fmt = inst->fmt_src;
|
||||||
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
|
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
|
||||||
|
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
|
||||||
codec_align = DEFAULT_CODEC_ALIGNMENT;
|
inst->codec = fmt->fmt.pix_mp.pixelformat;
|
||||||
|
codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16;
|
||||||
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align);
|
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align);
|
||||||
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align);
|
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align);
|
||||||
fmt->fmt.pix_mp.num_planes = 1;
|
fmt->fmt.pix_mp.num_planes = 1;
|
||||||
|
|||||||
@@ -8,6 +8,17 @@
|
|||||||
|
|
||||||
struct iris_inst;
|
struct iris_inst;
|
||||||
|
|
||||||
|
enum iris_fmt_type {
|
||||||
|
IRIS_FMT_H264,
|
||||||
|
IRIS_FMT_HEVC,
|
||||||
|
IRIS_FMT_VP9,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iris_fmt {
|
||||||
|
u32 pixfmt;
|
||||||
|
u32 type;
|
||||||
|
};
|
||||||
|
|
||||||
int iris_vdec_inst_init(struct iris_inst *inst);
|
int iris_vdec_inst_init(struct iris_inst *inst);
|
||||||
void iris_vdec_inst_deinit(struct iris_inst *inst);
|
void iris_vdec_inst_deinit(struct iris_inst *inst);
|
||||||
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
|
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
|
||||||
|
|||||||
@@ -278,9 +278,6 @@ static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f)
|
|||||||
{
|
{
|
||||||
struct iris_inst *inst = iris_get_inst(filp, NULL);
|
struct iris_inst *inst = iris_get_inst(filp, NULL);
|
||||||
|
|
||||||
if (f->index)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return iris_vdec_enum_fmt(inst, f);
|
return iris_vdec_enum_fmt(inst, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user