media: meson: vdec: add VP9 decoder support

This adds VP9 decoding for the Amlogic GXL, G12A & SM1 SoCs, using
the commong "HEVC" HW decoder.

For G12A & SM1, it uses the IOMMU support from the firmware.

For 10bit decoding, the firmware can only decode in the proprietary
Amlogic Framebuffer Compression format, but can output in 8bit NV12
buffer while writing the decoded frame.

Signed-off-by: Maxime Jourdan <mjourdan@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Maxime Jourdan 2020-03-04 10:46:25 +01:00 committed by Mauro Carvalho Chehab
parent e9a3eb4819
commit 00c43088aa
7 changed files with 2209 additions and 1 deletions

View File

@ -3,6 +3,6 @@
meson-vdec-objs = esparser.o vdec.o vdec_helpers.o vdec_platform.o
meson-vdec-objs += vdec_1.o vdec_hevc.o
meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_hevc_common.o
meson-vdec-objs += codec_mpeg12.o codec_h264.o codec_hevc_common.o codec_vp9.o
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr>
*/
#ifndef __MESON_VDEC_CODEC_VP9_H_
#define __MESON_VDEC_CODEC_VP9_H_
#include "vdec.h"
extern struct amvdec_codec_ops codec_vp9_ops;
#endif

View File

@ -122,6 +122,8 @@
#define HEVC_MPRED_L0_REF00_POC 0xc880
#define HEVC_MPRED_L1_REF00_POC 0xc8c0
#define HEVC_MPRED_CTRL4 0xc930
#define HEVC_MPRED_CUR_POC 0xc980
#define HEVC_MPRED_COL_POC 0xc984
#define HEVC_MPRED_MV_RD_END_ADDR 0xc988
@ -140,6 +142,10 @@
#define HEVCD_IPP_LINEBUFF_BASE 0xd024
#define HEVCD_IPP_AXIIF_CONFIG 0xd02c
#define VP9D_MPP_REF_SCALE_ENBL 0xd104
#define VP9D_MPP_REFINFO_TBL_ACCCONFIG 0xd108
#define VP9D_MPP_REFINFO_DATA 0xd10c
#define HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR 0xd180
#define HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR 0xd184
#define HEVCD_MPP_ANC2AXI_TBL_DATA 0xd190
@ -164,6 +170,7 @@
#define HEVC_DBLK_CFG9 0xd424
#define HEVC_DBLK_CFGA 0xd428
#define HEVC_DBLK_STS0 0xd42c
#define HEVC_DBLK_CFGB 0xd42c
#define HEVC_DBLK_STS1 0xd430
#define HEVC_DBLK_CFGE 0xd438

View File

@ -395,6 +395,7 @@ static void vdec_reset_bufs_recycle(struct amvdec_session *sess)
static void vdec_stop_streaming(struct vb2_queue *q)
{
struct amvdec_session *sess = vb2_get_drv_priv(q);
struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
struct amvdec_core *core = sess->core;
struct vb2_v4l2_buffer *buf;
@ -423,6 +424,10 @@ static void vdec_stop_streaming(struct vb2_queue *q)
sess->streamon_out = 0;
} else {
/* Drain remaining refs if was still running */
if (sess->status >= STATUS_RUNNING && codec_ops->drain)
codec_ops->drain(sess);
while ((buf = v4l2_m2m_dst_buf_remove(sess->m2m_ctx)))
v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);

View File

@ -299,6 +299,10 @@ static void dst_buf_done(struct amvdec_session *sess,
sess->sequence_cap - 1);
v4l2_event_queue_fh(&sess->fh, &ev);
vbuf->flags |= V4L2_BUF_FLAG_LAST;
} else if (sess->status == STATUS_NEEDS_RESUME) {
/* Mark LAST for drained show frames during a source change */
vbuf->flags |= V4L2_BUF_FLAG_LAST;
sess->sequence_cap = 0;
} else if (sess->should_stop)
dev_dbg(dev, "should_stop, %u bufs remain\n",
atomic_read(&sess->esparser_queued_bufs));

View File

@ -8,8 +8,10 @@
#include "vdec.h"
#include "vdec_1.h"
#include "vdec_hevc.h"
#include "codec_mpeg12.h"
#include "codec_h264.h"
#include "codec_vp9.h"
static const struct amvdec_format vdec_formats_gxbb[] = {
{
@ -51,6 +53,18 @@ static const struct amvdec_format vdec_formats_gxbb[] = {
static const struct amvdec_format vdec_formats_gxl[] = {
{
.pixfmt = V4L2_PIX_FMT_VP9,
.min_buffers = 16,
.max_buffers = 24,
.max_width = 3840,
.max_height = 2160,
.vdec_ops = &vdec_hevc_ops,
.codec_ops = &codec_vp9_ops,
.firmware_path = "meson/vdec/gxl_vp9.bin",
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
.flags = V4L2_FMT_FLAG_COMPRESSED |
V4L2_FMT_FLAG_DYN_RESOLUTION,
}, {
.pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2,
.max_buffers = 24,
@ -127,6 +141,18 @@ static const struct amvdec_format vdec_formats_gxm[] = {
static const struct amvdec_format vdec_formats_g12a[] = {
{
.pixfmt = V4L2_PIX_FMT_VP9,
.min_buffers = 16,
.max_buffers = 24,
.max_width = 3840,
.max_height = 2160,
.vdec_ops = &vdec_hevc_ops,
.codec_ops = &codec_vp9_ops,
.firmware_path = "meson/vdec/g12a_vp9.bin",
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
.flags = V4L2_FMT_FLAG_COMPRESSED |
V4L2_FMT_FLAG_DYN_RESOLUTION,
}, {
.pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2,
.max_buffers = 24,
@ -165,6 +191,18 @@ static const struct amvdec_format vdec_formats_g12a[] = {
static const struct amvdec_format vdec_formats_sm1[] = {
{
.pixfmt = V4L2_PIX_FMT_VP9,
.min_buffers = 16,
.max_buffers = 24,
.max_width = 3840,
.max_height = 2160,
.vdec_ops = &vdec_hevc_ops,
.codec_ops = &codec_vp9_ops,
.firmware_path = "meson/vdec/sm1_vp9_mmu.bin",
.pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
.flags = V4L2_FMT_FLAG_COMPRESSED |
V4L2_FMT_FLAG_DYN_RESOLUTION,
}, {
.pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2,
.max_buffers = 24,