Commit 00c43088 authored by Maxime Jourdan's avatar Maxime Jourdan Committed by Mauro Carvalho Chehab

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: default avatarMaxime Jourdan <mjourdan@baylibre.com>
Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Tested-by: default avatarKevin Hilman <khilman@baylibre.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent e9a3eb48
...@@ -3,6 +3,6 @@ ...@@ -3,6 +3,6 @@
meson-vdec-objs = esparser.o vdec.o vdec_helpers.o vdec_platform.o 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 += 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 obj-$(CONFIG_VIDEO_MESON_VDEC) += meson-vdec.o
This diff is collapsed.
/* 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
...@@ -122,6 +122,8 @@ ...@@ -122,6 +122,8 @@
#define HEVC_MPRED_L0_REF00_POC 0xc880 #define HEVC_MPRED_L0_REF00_POC 0xc880
#define HEVC_MPRED_L1_REF00_POC 0xc8c0 #define HEVC_MPRED_L1_REF00_POC 0xc8c0
#define HEVC_MPRED_CTRL4 0xc930
#define HEVC_MPRED_CUR_POC 0xc980 #define HEVC_MPRED_CUR_POC 0xc980
#define HEVC_MPRED_COL_POC 0xc984 #define HEVC_MPRED_COL_POC 0xc984
#define HEVC_MPRED_MV_RD_END_ADDR 0xc988 #define HEVC_MPRED_MV_RD_END_ADDR 0xc988
...@@ -140,6 +142,10 @@ ...@@ -140,6 +142,10 @@
#define HEVCD_IPP_LINEBUFF_BASE 0xd024 #define HEVCD_IPP_LINEBUFF_BASE 0xd024
#define HEVCD_IPP_AXIIF_CONFIG 0xd02c #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_CONF_ADDR 0xd180
#define HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR 0xd184 #define HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR 0xd184
#define HEVCD_MPP_ANC2AXI_TBL_DATA 0xd190 #define HEVCD_MPP_ANC2AXI_TBL_DATA 0xd190
...@@ -164,6 +170,7 @@ ...@@ -164,6 +170,7 @@
#define HEVC_DBLK_CFG9 0xd424 #define HEVC_DBLK_CFG9 0xd424
#define HEVC_DBLK_CFGA 0xd428 #define HEVC_DBLK_CFGA 0xd428
#define HEVC_DBLK_STS0 0xd42c #define HEVC_DBLK_STS0 0xd42c
#define HEVC_DBLK_CFGB 0xd42c
#define HEVC_DBLK_STS1 0xd430 #define HEVC_DBLK_STS1 0xd430
#define HEVC_DBLK_CFGE 0xd438 #define HEVC_DBLK_CFGE 0xd438
......
...@@ -395,6 +395,7 @@ static void vdec_reset_bufs_recycle(struct amvdec_session *sess) ...@@ -395,6 +395,7 @@ static void vdec_reset_bufs_recycle(struct amvdec_session *sess)
static void vdec_stop_streaming(struct vb2_queue *q) static void vdec_stop_streaming(struct vb2_queue *q)
{ {
struct amvdec_session *sess = vb2_get_drv_priv(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 amvdec_core *core = sess->core;
struct vb2_v4l2_buffer *buf; struct vb2_v4l2_buffer *buf;
...@@ -423,6 +424,10 @@ static void vdec_stop_streaming(struct vb2_queue *q) ...@@ -423,6 +424,10 @@ static void vdec_stop_streaming(struct vb2_queue *q)
sess->streamon_out = 0; sess->streamon_out = 0;
} else { } 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))) while ((buf = v4l2_m2m_dst_buf_remove(sess->m2m_ctx)))
v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
......
...@@ -299,6 +299,10 @@ static void dst_buf_done(struct amvdec_session *sess, ...@@ -299,6 +299,10 @@ static void dst_buf_done(struct amvdec_session *sess,
sess->sequence_cap - 1); sess->sequence_cap - 1);
v4l2_event_queue_fh(&sess->fh, &ev); v4l2_event_queue_fh(&sess->fh, &ev);
vbuf->flags |= V4L2_BUF_FLAG_LAST; 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) } else if (sess->should_stop)
dev_dbg(dev, "should_stop, %u bufs remain\n", dev_dbg(dev, "should_stop, %u bufs remain\n",
atomic_read(&sess->esparser_queued_bufs)); atomic_read(&sess->esparser_queued_bufs));
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
#include "vdec.h" #include "vdec.h"
#include "vdec_1.h" #include "vdec_1.h"
#include "vdec_hevc.h"
#include "codec_mpeg12.h" #include "codec_mpeg12.h"
#include "codec_h264.h" #include "codec_h264.h"
#include "codec_vp9.h"
static const struct amvdec_format vdec_formats_gxbb[] = { static const struct amvdec_format vdec_formats_gxbb[] = {
{ {
...@@ -51,6 +53,18 @@ 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[] = { 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, .pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2, .min_buffers = 2,
.max_buffers = 24, .max_buffers = 24,
...@@ -127,6 +141,18 @@ static const struct amvdec_format vdec_formats_gxm[] = { ...@@ -127,6 +141,18 @@ static const struct amvdec_format vdec_formats_gxm[] = {
static const struct amvdec_format vdec_formats_g12a[] = { 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, .pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2, .min_buffers = 2,
.max_buffers = 24, .max_buffers = 24,
...@@ -165,6 +191,18 @@ static const struct amvdec_format vdec_formats_g12a[] = { ...@@ -165,6 +191,18 @@ static const struct amvdec_format vdec_formats_g12a[] = {
static const struct amvdec_format vdec_formats_sm1[] = { 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, .pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2, .min_buffers = 2,
.max_buffers = 24, .max_buffers = 24,
......
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