Merge pull request #5143 from knaerzche/rk-update-2

Rockchip: next update
This commit is contained in:
CvH 2021-02-16 18:52:07 +01:00 committed by GitHub
commit 058b49e3e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 4924 additions and 94 deletions

View File

@ -1,13 +1,13 @@
From 050dd4323a9fe8515259fe855c31da6d1ad459e2 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 5 Aug 2018 20:58:54 +0200
Subject: [PATCH] rockchip: rk3288: get serial and ethaddr from efuse
---
arch/arm/dts/rk3288.dtsi | 5 ++---
configs/miqi-rk3288_defconfig | 2 ++
configs/tinker-rk3288_defconfig | 1 +
3 files changed, 5 insertions(+), 3 deletions(-)
configs/miqi-rk3288_defconfig | 3 +++
configs/tinker-rk3288_defconfig | 2 ++
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
index 20adb0dece..8b085ee6dc 100644
@ -26,27 +26,29 @@ index 20adb0dece..8b085ee6dc 100644
gic: interrupt-controller@ffc01000 {
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
index 09d5979dff..ffbe701cfd 100644
index 09d5979dff..77d8f7dffc 100644
--- a/configs/miqi-rk3288_defconfig
+++ b/configs/miqi-rk3288_defconfig
@@ -48,6 +48,8 @@ CONFIG_ROCKCHIP_GPIO=y
@@ -48,6 +48,9 @@ CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_DM_KEY=y
CONFIG_ADC_KEY=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
+CONFIG_SHA256=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_DM_ETH=y
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index 3abf7c1088..0afc0a35e1 100644
index 3abf7c1088..52196194c9 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -46,6 +46,7 @@ CONFIG_SPL_CLK=y
@@ -46,6 +46,8 @@ CONFIG_SPL_CLK=y
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
+CONFIG_SHA256=y
CONFIG_I2C_EEPROM=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y

View File

@ -2929,6 +2929,7 @@ CONFIG_SMS_SIANO_RC=y
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
CONFIG_VIDEO_ROCKCHIP_IEP=m
CONFIG_VIDEO_ROCKCHIP_RGA=m
# CONFIG_DVB_PLATFORM_DRIVERS is not set

View File

@ -3019,6 +3019,7 @@ CONFIG_SMS_SIANO_RC=y
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
CONFIG_VIDEO_ROCKCHIP_IEP=m
CONFIG_VIDEO_ROCKCHIP_RGA=m
# CONFIG_DVB_PLATFORM_DRIVERS is not set

View File

@ -0,0 +1,12 @@
rockchip/*
ath10k/QCA6174
ath10k/QCA9377
ath10k/QCA9887
ath10k/QCA9888
ath10k/QCA988X
ath10k/QCA9984
ath10k/QCA99X0
iwlwifi-4965-2.ucode
iwlwifi-5*
iwlwifi-6*
mwlwifi/

View File

@ -2091,7 +2091,8 @@ CONFIG_AR5523=m
# CONFIG_WIL6210 is not set
CONFIG_ATH10K=m
CONFIG_ATH10K_CE=y
# CONFIG_ATH10K_PCI is not set
CONFIG_ATH10K_PCI=m
# CONFIG_ATH10K_AHB is not set
# CONFIG_ATH10K_SDIO is not set
CONFIG_ATH10K_USB=m
# CONFIG_ATH10K_DEBUG is not set
@ -2125,18 +2126,39 @@ CONFIG_BRCMUTIL=m
# CONFIG_BRCMSMAC is not set
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_PROTO_BCDC=y
CONFIG_BRCMFMAC_PROTO_MSGBUF=y
CONFIG_BRCMFMAC_SDIO=y
CONFIG_BRCMFMAC_USB=y
# CONFIG_BRCMFMAC_PCIE is not set
CONFIG_BRCMFMAC_PCIE=y
# CONFIG_BRCM_TRACING is not set
# CONFIG_BRCMDBG is not set
CONFIG_WLAN_VENDOR_CISCO=y
CONFIG_WLAN_VENDOR_INTEL=y
# CONFIG_IPW2100 is not set
# CONFIG_IPW2200 is not set
# CONFIG_IWL4965 is not set
CONFIG_IWLEGACY=m
CONFIG_IWL4965=m
# CONFIG_IWL3945 is not set
# CONFIG_IWLWIFI is not set
#
# iwl3945 / iwl4965 Debugging Options
#
# CONFIG_IWLEGACY_DEBUG is not set
# end of iwl3945 / iwl4965 Debugging Options
CONFIG_IWLWIFI=m
CONFIG_IWLWIFI_LEDS=y
CONFIG_IWLDVM=m
CONFIG_IWLMVM=m
CONFIG_IWLWIFI_OPMODE_MODULAR=y
# CONFIG_IWLWIFI_BCAST_FILTERING is not set
#
# Debugging Options
#
# CONFIG_IWLWIFI_DEBUG is not set
# end of Debugging Options
CONFIG_WLAN_VENDOR_INTERSIL=y
# CONFIG_HOSTAP is not set
# CONFIG_HERMES is not set
@ -2158,7 +2180,7 @@ CONFIG_LIBERTAS_THINFIRM=m
CONFIG_LIBERTAS_THINFIRM_USB=m
CONFIG_MWIFIEX=m
# CONFIG_MWIFIEX_SDIO is not set
# CONFIG_MWIFIEX_PCIE is not set
CONFIG_MWIFIEX_PCIE=m
CONFIG_MWIFIEX_USB=m
# CONFIG_MWL8K is not set
CONFIG_WLAN_VENDOR_MEDIATEK=y
@ -2171,17 +2193,17 @@ CONFIG_MT76x02_LIB=m
CONFIG_MT76x02_USB=m
CONFIG_MT76x0_COMMON=m
CONFIG_MT76x0U=m
# CONFIG_MT76x0E is not set
CONFIG_MT76x0E=m
CONFIG_MT76x2_COMMON=m
# CONFIG_MT76x2E is not set
CONFIG_MT76x2E=m
CONFIG_MT76x2U=m
# CONFIG_MT7603E is not set
CONFIG_MT7603E=m
CONFIG_MT7615_COMMON=m
# CONFIG_MT7615E is not set
CONFIG_MT7615E=m
CONFIG_MT7663_USB_SDIO_COMMON=m
CONFIG_MT7663U=m
CONFIG_MT7663S=m
# CONFIG_MT7915E is not set
CONFIG_MT7915E=m
CONFIG_WLAN_VENDOR_MICROCHIP=y
# CONFIG_WILC1000_SDIO is not set
# CONFIG_WILC1000_SPI is not set
@ -3499,6 +3521,7 @@ CONFIG_SMS_SIANO_RC=y
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
CONFIG_VIDEO_ROCKCHIP_IEP=m
CONFIG_VIDEO_ROCKCHIP_RGA=m
# CONFIG_DVB_PLATFORM_DRIVERS is not set

View File

@ -0,0 +1,924 @@
From 39069d9cc03a42cd497dd6b9756116ff4b684a5d Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Tue, 3 Dec 2019 21:01:18 +0100
Subject: [PATCH] WIP deint filter
---
libavfilter/Makefile | 1 +
libavfilter/allfilters.c | 1 +
libavfilter/vf_deinterlace_v4l2m2m.c | 879 +++++++++++++++++++++++++++
3 files changed, 881 insertions(+)
create mode 100644 libavfilter/vf_deinterlace_v4l2m2m.c
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 512354065305..625fd29f9313 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -218,6 +218,7 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o
OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o
OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o
OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o
+OBJS-$(CONFIG_DEINTERLACE_V4L2M2M_FILTER) += vf_deinterlace_v4l2m2m.o
OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o
OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o
OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 1183e4026751..fe5a2e8c02e8 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -204,6 +204,7 @@ extern AVFilter ff_vf_dedot;
extern AVFilter ff_vf_deflate;
extern AVFilter ff_vf_deflicker;
extern AVFilter ff_vf_deinterlace_qsv;
+extern AVFilter ff_vf_deinterlace_v4l2m2m;
extern AVFilter ff_vf_deinterlace_vaapi;
extern AVFilter ff_vf_dejudder;
extern AVFilter ff_vf_delogo;
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
new file mode 100644
index 000000000000..1029e5b620fd
--- /dev/null
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
@@ -0,0 +1,879 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * deinterlace video filter - V4L2 M2M
+ */
+
+#include <drm_fourcc.h>
+
+#include <linux/videodev2.h>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdatomic.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/common.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_drm.h"
+#include "libavutil/internal.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/time.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct V4L2Queue V4L2Queue;
+typedef struct DeintV4L2M2MContextShared DeintV4L2M2MContextShared;
+
+typedef struct V4L2PlaneInfo {
+ int bytesperline;
+ size_t length;
+} V4L2PlaneInfo;
+
+typedef struct V4L2Buffer {
+ int enqueued;
+ int reenqueue;
+ int fd;
+ struct v4l2_buffer buffer;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ int num_planes;
+ V4L2PlaneInfo plane_info[VIDEO_MAX_PLANES];
+ AVDRMFrameDescriptor drm_frame;
+ V4L2Queue *q;
+} V4L2Buffer;
+
+typedef struct V4L2Queue {
+ struct v4l2_format format;
+ int num_buffers;
+ V4L2Buffer *buffers;
+ DeintV4L2M2MContextShared *ctx;
+} V4L2Queue;
+
+typedef struct DeintV4L2M2MContextShared {
+ int fd;
+ int done;
+ int width;
+ int height;
+ int orig_width;
+ int orig_height;
+ atomic_uint refcount;
+
+ AVBufferRef *hw_frames_ctx;
+
+ int frame_count;
+ AVFrame *frames[2];
+
+ V4L2Queue output;
+ V4L2Queue capture;
+} DeintV4L2M2MContextShared;
+
+typedef struct DeintV4L2M2MContext {
+ const AVClass *class;
+
+ DeintV4L2M2MContextShared *shared;
+} DeintV4L2M2MContext;
+
+static int deint_v4l2m2m_prepare_context(DeintV4L2M2MContextShared *ctx)
+{
+ struct v4l2_capability cap;
+ int ret;
+
+ memset(&cap, 0, sizeof(cap));
+ ret = ioctl(ctx->fd, VIDIOC_QUERYCAP, &cap);
+ if (ret < 0)
+ return ret;
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING))
+ return AVERROR(EINVAL);
+
+ if (cap.capabilities & V4L2_CAP_VIDEO_M2M) {
+ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ return 0;
+ }
+
+ if (cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE) {
+ ctx->capture.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ctx->output.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+ return 0;
+ }
+
+ return AVERROR(EINVAL);
+}
+
+static int deint_v4l2m2m_try_format(V4L2Queue *queue)
+{
+ struct v4l2_format *fmt = &queue->format;
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
+ int ret, field;
+
+ ret = ioctl(ctx->fd, VIDIOC_G_FMT, fmt);
+ if (ret)
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_G_FMT failed: %d\n", ret);
+
+ if (V4L2_TYPE_IS_OUTPUT(fmt->type))
+ field = V4L2_FIELD_INTERLACED_TB;
+ else
+ field = V4L2_FIELD_NONE;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
+ fmt->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
+ fmt->fmt.pix_mp.field = field;
+ fmt->fmt.pix_mp.width = ctx->width;
+ fmt->fmt.pix_mp.height = ctx->height;
+ } else {
+ fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
+ fmt->fmt.pix.field = field;
+ fmt->fmt.pix.width = ctx->width;
+ fmt->fmt.pix.height = ctx->height;
+ }
+
+ ret = ioctl(ctx->fd, VIDIOC_TRY_FMT, fmt);
+ if (ret)
+ return AVERROR(EINVAL);
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
+ if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12 ||
+ fmt->fmt.pix_mp.field != field) {
+ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
+
+ return AVERROR(EINVAL);
+ }
+ } else {
+ if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12 ||
+ fmt->fmt.pix.field != field) {
+ av_log(NULL, AV_LOG_DEBUG, "format not supported for type %d\n", fmt->type);
+
+ return AVERROR(EINVAL);
+ }
+ }
+
+ return 0;
+}
+
+static int deint_v4l2m2m_set_format(V4L2Queue *queue, uint32_t field, int width, int height)
+{
+ struct v4l2_format *fmt = &queue->format;
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
+ int ret;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(fmt->type)) {
+ fmt->fmt.pix_mp.field = field;
+ fmt->fmt.pix_mp.width = width;
+ fmt->fmt.pix_mp.height = height;
+ /* TODO: bytesperline and imagesize */
+ } else {
+ fmt->fmt.pix.field = field;
+ fmt->fmt.pix.width = width;
+ fmt->fmt.pix.height = height;
+ fmt->fmt.pix.sizeimage = 0;
+ fmt->fmt.pix.bytesperline = 0;
+ }
+
+ ret = ioctl(ctx->fd, VIDIOC_S_FMT, fmt);
+ if (ret)
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_S_FMT failed: %d\n", ret);
+
+ return ret;
+}
+
+static int deint_v4l2m2m_probe_device(DeintV4L2M2MContextShared *ctx, char *node)
+{
+ int ret;
+
+ ctx->fd = open(node, O_RDWR | O_NONBLOCK, 0);
+ if (ctx->fd < 0)
+ return AVERROR(errno);
+
+ ret = deint_v4l2m2m_prepare_context(ctx);
+ if (ret)
+ goto fail;
+
+ ret = deint_v4l2m2m_try_format(&ctx->capture);
+ if (ret)
+ goto fail;
+
+ ret = deint_v4l2m2m_try_format(&ctx->output);
+ if (ret)
+ goto fail;
+
+ return 0;
+
+fail:
+ close(ctx->fd);
+ ctx->fd = -1;
+
+ return ret;
+}
+
+static int deint_v4l2m2m_find_device(DeintV4L2M2MContextShared *ctx)
+{
+ int ret = AVERROR(EINVAL);
+ struct dirent *entry;
+ char node[PATH_MAX];
+ DIR *dirp;
+
+ dirp = opendir("/dev");
+ if (!dirp)
+ return AVERROR(errno);
+
+ for (entry = readdir(dirp); entry; entry = readdir(dirp)) {
+
+ if (strncmp(entry->d_name, "video", 5))
+ continue;
+
+ snprintf(node, sizeof(node), "/dev/%s", entry->d_name);
+ av_log(NULL, AV_LOG_DEBUG, "probing device %s\n", node);
+ ret = deint_v4l2m2m_probe_device(ctx, node);
+ if (!ret)
+ break;
+ }
+
+ closedir(dirp);
+
+ if (ret) {
+ av_log(NULL, AV_LOG_ERROR, "Could not find a valid device\n");
+ ctx->fd = -1;
+
+ return ret;
+ }
+
+ av_log(NULL, AV_LOG_INFO, "Using device %s\n", node);
+
+ return 0;
+}
+
+static int deint_v4l2m2m_enqueue_buffer(V4L2Buffer *buf)
+{
+ int ret;
+
+ ret = ioctl(buf->q->ctx->fd, VIDIOC_QBUF, &buf->buffer);
+ if (ret < 0)
+ return AVERROR(errno);
+
+ buf->enqueued = 1;
+
+ return 0;
+}
+
+static int v4l2_buffer_export_drm(V4L2Buffer* avbuf)
+{
+ struct v4l2_exportbuffer expbuf;
+ int i, ret;
+
+ for (i = 0; i < avbuf->num_planes; i++) {
+ memset(&expbuf, 0, sizeof(expbuf));
+
+ expbuf.index = avbuf->buffer.index;
+ expbuf.type = avbuf->buffer.type;
+ expbuf.plane = i;
+
+ ret = ioctl(avbuf->q->ctx->fd, VIDIOC_EXPBUF, &expbuf);
+ if (ret < 0)
+ return AVERROR(errno);
+
+ avbuf->fd = expbuf.fd;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(avbuf->buffer.type)) {
+ /* drm frame */
+ avbuf->drm_frame.objects[i].size = avbuf->buffer.m.planes[i].length;
+ avbuf->drm_frame.objects[i].fd = expbuf.fd;
+ avbuf->drm_frame.objects[i].format_modifier = DRM_FORMAT_MOD_LINEAR;
+ } else {
+ /* drm frame */
+ avbuf->drm_frame.objects[0].size = avbuf->buffer.length;
+ avbuf->drm_frame.objects[0].fd = expbuf.fd;
+ avbuf->drm_frame.objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR;
+ }
+ }
+
+ return 0;
+}
+
+static int deint_v4l2m2m_allocate_buffers(V4L2Queue *queue)
+{
+ struct v4l2_format *fmt = &queue->format;
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
+ struct v4l2_requestbuffers req;
+ int ret, i, j, multiplanar;
+ uint32_t memory;
+
+ memory = V4L2_TYPE_IS_OUTPUT(fmt->type) ?
+ V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP;
+
+ multiplanar = V4L2_TYPE_IS_MULTIPLANAR(fmt->type);
+
+ memset(&req, 0, sizeof(req));
+ req.count = queue->num_buffers;
+ req.memory = memory;
+ req.type = fmt->type;
+
+ ret = ioctl(ctx->fd, VIDIOC_REQBUFS, &req);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "VIDIOC_REQBUFS failed: %s\n", strerror(errno));
+
+ return AVERROR(errno);
+ }
+
+ queue->num_buffers = req.count;
+ queue->buffers = av_mallocz(queue->num_buffers * sizeof(V4L2Buffer));
+ if (!queue->buffers) {
+ av_log(NULL, AV_LOG_ERROR, "malloc enomem\n");
+
+ return AVERROR(ENOMEM);
+ }
+
+ for (i = 0; i < queue->num_buffers; i++) {
+ V4L2Buffer *buf = &queue->buffers[i];
+
+ buf->enqueued = 0;
+ buf->fd = -1;
+ buf->q = queue;
+
+ buf->buffer.type = fmt->type;
+ buf->buffer.memory = memory;
+ buf->buffer.index = i;
+
+ if (multiplanar) {
+ buf->buffer.length = VIDEO_MAX_PLANES;
+ buf->buffer.m.planes = buf->planes;
+ }
+
+ ret = ioctl(ctx->fd, VIDIOC_QUERYBUF, &buf->buffer);
+ if (ret < 0) {
+ ret = AVERROR(errno);
+
+ goto fail;
+ }
+
+ if (multiplanar)
+ buf->num_planes = buf->buffer.length;
+ else
+ buf->num_planes = 1;
+
+ for (j = 0; j < buf->num_planes; j++) {
+ V4L2PlaneInfo *info = &buf->plane_info[j];
+
+ if (multiplanar) {
+ info->bytesperline = fmt->fmt.pix_mp.plane_fmt[j].bytesperline;
+ info->length = buf->buffer.m.planes[j].length;
+ } else {
+ info->bytesperline = fmt->fmt.pix.bytesperline;
+ info->length = buf->buffer.length;
+ }
+ }
+
+ if (!V4L2_TYPE_IS_OUTPUT(fmt->type)) {
+ ret = deint_v4l2m2m_enqueue_buffer(buf);
+ if (ret)
+ goto fail;
+
+ ret = v4l2_buffer_export_drm(buf);
+ if (ret)
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ for (i = 0; i < queue->num_buffers; i++)
+ if (queue->buffers[i].fd >= 0)
+ close(queue->buffers[i].fd);
+ av_free(queue->buffers);
+ queue->buffers = NULL;
+
+ return ret;
+}
+
+static int deint_v4l2m2m_streamon(V4L2Queue *queue)
+{
+ int type = queue->format.type;
+ int ret;
+
+ ret = ioctl(queue->ctx->fd, VIDIOC_STREAMON, &type);
+ if (ret < 0)
+ return AVERROR(errno);
+
+ return 0;
+}
+
+static int deint_v4l2m2m_streamoff(V4L2Queue *queue)
+{
+ int type = queue->format.type;
+ int ret;
+
+ ret = ioctl(queue->ctx->fd, VIDIOC_STREAMOFF, &type);
+ if (ret < 0)
+ return AVERROR(errno);
+
+ return 0;
+}
+
+static V4L2Buffer* deint_v4l2m2m_dequeue_buffer(V4L2Queue *queue, int timeout)
+{
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
+ struct v4l2_buffer buf = { 0 };
+ V4L2Buffer* avbuf = NULL;
+ struct pollfd pfd;
+ short events;
+ int ret;
+
+ if (V4L2_TYPE_IS_OUTPUT(queue->format.type))
+ events = POLLOUT | POLLWRNORM;
+ else
+ events = POLLIN | POLLRDNORM;
+
+ pfd.events = events;
+ pfd.fd = ctx->fd;
+
+ for (;;) {
+ ret = poll(&pfd, 1, timeout);
+ if (ret > 0)
+ break;
+ if (errno == EINTR)
+ continue;
+ return NULL;
+ }
+
+ if (pfd.revents & POLLERR)
+ return NULL;
+
+ if (pfd.revents & events) {
+ memset(&buf, 0, sizeof(buf));
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.type = queue->format.type;
+ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) {
+ memset(planes, 0, sizeof(planes));
+ buf.length = VIDEO_MAX_PLANES;
+ buf.m.planes = planes;
+ }
+
+ ret = ioctl(ctx->fd, VIDIOC_DQBUF, &buf);
+ if (ret) {
+ if (errno != EAGAIN)
+ av_log(NULL, AV_LOG_DEBUG, "VIDIOC_DQBUF, errno (%s)\n",
+ av_err2str(AVERROR(errno)));
+ return NULL;
+ }
+
+ avbuf = &queue->buffers[buf.index];
+ avbuf->enqueued = 0;
+ avbuf->buffer = buf;
+ if (V4L2_TYPE_IS_MULTIPLANAR(queue->format.type)) {
+ memcpy(avbuf->planes, planes, sizeof(planes));
+ avbuf->buffer.m.planes = avbuf->planes;
+ }
+
+ return avbuf;
+ }
+
+ return NULL;
+}
+
+static V4L2Buffer *deint_v4l2m2m_find_free_buf(V4L2Queue *queue)
+{
+ int i;
+
+ for (i = 0; i < queue->num_buffers; i++)
+ if (!queue->buffers[i].enqueued)
+ return &queue->buffers[i];
+
+ return NULL;
+}
+
+static int deint_v4l2m2m_enqueue(V4L2Queue *queue, const AVFrame* frame)
+{
+ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)frame->data[0];
+ V4L2Buffer *buf;
+ int i;
+
+ if (V4L2_TYPE_IS_OUTPUT(queue->format.type))
+ while (deint_v4l2m2m_dequeue_buffer(queue, 0));
+
+ buf = deint_v4l2m2m_find_free_buf(queue);
+ if (!buf)
+ return AVERROR(ENOMEM);
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf->buffer.type))
+ for (i = 0; i < drm_desc->nb_objects; i++)
+ buf->buffer.m.planes[i].m.fd = drm_desc->objects[i].fd;
+ else
+ buf->buffer.m.fd = drm_desc->objects[0].fd;
+
+ return deint_v4l2m2m_enqueue_buffer(buf);
+}
+
+static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx)
+{
+ if (atomic_fetch_sub(&ctx->refcount, 1) == 1) {
+ V4L2Queue *capture = &ctx->capture;
+ V4L2Queue *output = &ctx->output;
+ int i;
+
+ av_log(NULL, AV_LOG_DEBUG, "%s - destroying context\n", __func__);
+
+ if (ctx->fd >= 0) {
+ deint_v4l2m2m_streamoff(capture);
+ deint_v4l2m2m_streamoff(output);
+ }
+
+ if (capture->buffers)
+ for (i = 0; i < capture->num_buffers; i++) {
+ capture->buffers[i].q = NULL;
+ if (capture->buffers[i].fd >= 0)
+ close(capture->buffers[i].fd);
+ }
+
+ for (i = 0; i < ctx->frame_count; i++)
+ av_frame_free(&ctx->frames[i]);
+
+ av_buffer_unref(&ctx->hw_frames_ctx);
+
+ if (capture->buffers)
+ av_free(capture->buffers);
+
+ if (output->buffers)
+ av_free(output->buffers);
+
+ if (ctx->fd >= 0) {
+ close(ctx->fd);
+ ctx->fd = -1;
+ }
+
+ av_free(ctx);
+ }
+}
+
+static void v4l2_free_buffer(void *opaque, uint8_t *unused)
+{
+ V4L2Buffer *buf = opaque;
+ DeintV4L2M2MContextShared *ctx = buf->q->ctx;
+
+ if (!ctx->done)
+ deint_v4l2m2m_enqueue_buffer(buf);
+
+ deint_v4l2m2m_destroy_context(ctx);
+}
+
+static uint8_t *v4l2_get_drm_frame(V4L2Buffer *avbuf, int height)
+{
+ AVDRMFrameDescriptor *drm_desc = &avbuf->drm_frame;
+ AVDRMLayerDescriptor *layer;
+
+ /* fill the DRM frame descriptor */
+ drm_desc->nb_objects = avbuf->num_planes;
+ drm_desc->nb_layers = 1;
+
+ layer = &drm_desc->layers[0];
+ layer->nb_planes = avbuf->num_planes;
+
+ for (int i = 0; i < avbuf->num_planes; i++) {
+ layer->planes[i].object_index = i;
+ layer->planes[i].offset = 0;
+ layer->planes[i].pitch = avbuf->plane_info[i].bytesperline;
+ }
+
+ layer->format = DRM_FORMAT_NV12;
+
+ if (avbuf->num_planes == 1) {
+ layer->nb_planes = 2;
+
+ layer->planes[1].object_index = 0;
+ layer->planes[1].offset = avbuf->plane_info[0].bytesperline * height;
+ layer->planes[1].pitch = avbuf->plane_info[0].bytesperline;
+ }
+
+ return (uint8_t *)drm_desc;
+}
+
+static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int timeout)
+{
+ DeintV4L2M2MContextShared *ctx = queue->ctx;
+ V4L2Buffer* avbuf;
+
+ avbuf = deint_v4l2m2m_dequeue_buffer(queue, timeout);
+ if (!avbuf) {
+ av_log(NULL, AV_LOG_ERROR, "dequeueing failed\n");
+ return AVERROR(EINVAL);
+ }
+
+ frame->buf[0] = av_buffer_create((uint8_t *) &avbuf->drm_frame,
+ sizeof(avbuf->drm_frame), v4l2_free_buffer,
+ avbuf, AV_BUFFER_FLAG_READONLY);
+ if (!frame->buf[0])
+ return AVERROR(ENOMEM);
+
+ atomic_fetch_add(&ctx->refcount, 1);
+
+ frame->data[0] = (uint8_t *)v4l2_get_drm_frame(avbuf, ctx->orig_height);
+ frame->format = AV_PIX_FMT_DRM_PRIME;
+ frame->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
+ frame->height = ctx->height;
+ frame->width = ctx->width;
+
+ if (avbuf->buffer.flags & V4L2_BUF_FLAG_ERROR) {
+ av_log(NULL, AV_LOG_ERROR, "driver decode error\n");
+ frame->decode_error_flags |= FF_DECODE_ERROR_INVALID_BITSTREAM;
+ }
+
+ return 0;
+}
+
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame, int field)
+{
+ DeintV4L2M2MContext *priv = avctx->priv;
+ DeintV4L2M2MContextShared *ctx = priv->shared;
+ AVFilterLink *outlink = avctx->outputs[0];
+ AVFrame *output_frame;
+ int err;
+
+ output_frame = av_frame_alloc();
+
+ if (!output_frame)
+ return AVERROR(ENOMEM);
+
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame, 500);
+ if (err < 0) {
+ av_log(priv, AV_LOG_ERROR, "no frame (field %d)\n", field);
+ goto fail;
+ }
+
+ err = av_frame_copy_props(output_frame, input_frame);
+ if (err < 0)
+ goto fail;
+
+ output_frame->interlaced_frame = 0;
+
+ if (field == 0) {
+ output_frame->pts *= 2;
+ } else {
+ int64_t cur_pts = ctx->frames[0]->pts;
+ int64_t next_pts = ctx->frames[1]->pts;
+
+ if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
+ output_frame->pts = next_pts + cur_pts;
+ } else {
+ output_frame->pts = AV_NOPTS_VALUE;
+ }
+ }
+ av_log(priv, AV_LOG_DEBUG, "pts: %"PRId64" (field %d)\n", output_frame->pts, field);
+
+ return ff_filter_frame(outlink, output_frame);
+
+fail:
+ av_frame_free(&output_frame);
+ return err;
+}
+
+static int deint_v4l2m2m_config_props(AVFilterLink *outlink)
+{
+ AVFilterLink *inlink = outlink->src->inputs[0];
+ AVFilterContext *avctx = outlink->src;
+ DeintV4L2M2MContext *priv = avctx->priv;
+ DeintV4L2M2MContextShared *ctx = priv->shared;
+ int ret;
+
+ ctx->height = avctx->inputs[0]->h;
+ ctx->width = avctx->inputs[0]->w;
+
+ outlink->frame_rate = av_mul_q(inlink->frame_rate,
+ (AVRational){ 2, 1 });
+ outlink->time_base = av_mul_q(inlink->time_base,
+ (AVRational){ 1, 2 });
+
+ ret = deint_v4l2m2m_find_device(ctx);
+ if (ret)
+ return ret;
+
+ if (!inlink->hw_frames_ctx) {
+ av_log(priv, AV_LOG_ERROR, "No hw context provided on input\n");
+ return AVERROR(EINVAL);
+ }
+
+ ctx->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
+ if (!ctx->hw_frames_ctx)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static int deint_v4l2m2m_query_formats(AVFilterContext *avctx)
+{
+ static const enum AVPixelFormat pixel_formats[] = {
+ AV_PIX_FMT_DRM_PRIME,
+ AV_PIX_FMT_NONE,
+ };
+
+ return ff_set_common_formats(avctx, ff_make_format_list(pixel_formats));
+}
+
+static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+ AVFilterContext *avctx = link->dst;
+ DeintV4L2M2MContext *priv = avctx->priv;
+ DeintV4L2M2MContextShared *ctx = priv->shared;
+ V4L2Queue *capture = &ctx->capture;
+ V4L2Queue *output = &ctx->output;
+ int ret;
+
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64"\n", in->pts);
+ if (!ctx->frame_count) {
+ AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
+ unsigned int field;
+
+ ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
+ ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
+
+ if (in->top_field_first)
+ field = V4L2_FIELD_INTERLACED_TB;
+ else
+ field = V4L2_FIELD_INTERLACED_BT;
+
+ ret = deint_v4l2m2m_set_format(output, field, ctx->orig_width, ctx->orig_height);
+ if (ret)
+ return ret;
+
+ ret = deint_v4l2m2m_set_format(capture, V4L2_FIELD_NONE, ctx->orig_width, ctx->orig_height);
+ if (ret)
+ return ret;
+
+ ret = deint_v4l2m2m_allocate_buffers(capture);
+ if (ret)
+ return ret;
+
+ ret = deint_v4l2m2m_streamon(capture);
+ if (ret)
+ return ret;
+
+ ret = deint_v4l2m2m_allocate_buffers(output);
+ if (ret)
+ return ret;
+
+ ret = deint_v4l2m2m_streamon(output);
+ if (ret)
+ return ret;
+ }
+
+ if (ctx->frame_count < 2) {
+ ctx->frames[ctx->frame_count++] = in;
+ } else {
+ av_frame_free(&ctx->frames[0]);
+ ctx->frames[0] = ctx->frames[1];
+ ctx->frames[1] = in;
+ }
+
+ ret = deint_v4l2m2m_enqueue(output, in);
+ if (ret)
+ return ret;
+
+ if (ctx->frame_count == 2) {
+ ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 0);
+ if (ret)
+ return ret;
+
+ ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 1);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
+{
+ DeintV4L2M2MContext *priv = avctx->priv;
+ DeintV4L2M2MContextShared *ctx;
+
+ ctx = av_mallocz(sizeof(DeintV4L2M2MContextShared));
+ if (!ctx)
+ return AVERROR(ENOMEM);
+
+ priv->shared = ctx;
+ ctx->fd = -1;
+ ctx->output.ctx = ctx;
+ ctx->output.num_buffers = 6;
+ ctx->capture.ctx = ctx;
+ ctx->capture.num_buffers = 6;
+ ctx->done = 0;
+ atomic_init(&ctx->refcount, 1);
+
+ return 0;
+}
+
+static void deint_v4l2m2m_uninit(AVFilterContext *avctx)
+{
+ DeintV4L2M2MContext *priv = avctx->priv;
+ DeintV4L2M2MContextShared *ctx = priv->shared;
+
+ ctx->done = 1;
+ deint_v4l2m2m_destroy_context(ctx);
+}
+
+static const AVOption deinterlace_v4l2m2m_options[] = {
+ { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(deinterlace_v4l2m2m);
+
+static const AVFilterPad deint_v4l2m2m_inputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .filter_frame = deint_v4l2m2m_filter_frame,
+ },
+ { NULL }
+};
+
+static const AVFilterPad deint_v4l2m2m_outputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .config_props = deint_v4l2m2m_config_props,
+ },
+ { NULL }
+};
+
+AVFilter ff_vf_deinterlace_v4l2m2m = {
+ .name = "deinterlace_v4l2m2m",
+ .description = NULL_IF_CONFIG_SMALL("V4L2 M2M deinterlacer"),
+ .priv_size = sizeof(DeintV4L2M2MContext),
+ .init = &deint_v4l2m2m_init,
+ .uninit = &deint_v4l2m2m_uninit,
+ .query_formats = &deint_v4l2m2m_query_formats,
+ .inputs = deint_v4l2m2m_inputs,
+ .outputs = deint_v4l2m2m_outputs,
+ .priv_class = &deinterlace_v4l2m2m_class,
+};
--
2.29.2

View File

@ -0,0 +1,230 @@
From 6bea46839ba23bffaa093bb9ed805d571aaa66ea Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 30 Sep 2020 21:11:34 +0200
Subject: [PATCH] libavfilter: v4l2deinterlace: dequeue both destination
buffers on time
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
libavfilter/vf_deinterlace_v4l2m2m.c | 140 +++++++++++++++++----------
1 file changed, 88 insertions(+), 52 deletions(-)
diff --git a/libavfilter/vf_deinterlace_v4l2m2m.c b/libavfilter/vf_deinterlace_v4l2m2m.c
index 1029e5b620fd..72d28333ffa7 100644
--- a/libavfilter/vf_deinterlace_v4l2m2m.c
+++ b/libavfilter/vf_deinterlace_v4l2m2m.c
@@ -89,8 +89,14 @@ typedef struct DeintV4L2M2MContextShared {
AVBufferRef *hw_frames_ctx;
- int frame_count;
- AVFrame *frames[2];
+ /*
+ * TODO: check if its really neccessary to hold this
+ * ref, it's only used for freeing av_frame on decoding
+ * end/abort
+ */
+ AVFrame *cur_in_frame;
+ AVFrame *prev_in_frame;
+ unsigned int field_order;
V4L2Queue output;
V4L2Queue capture;
@@ -557,8 +563,11 @@ static void deint_v4l2m2m_destroy_context(DeintV4L2M2MContextShared *ctx)
close(capture->buffers[i].fd);
}
- for (i = 0; i < ctx->frame_count; i++)
- av_frame_free(&ctx->frames[i]);
+ if (ctx->cur_in_frame)
+ av_frame_free(&ctx->cur_in_frame);
+
+ if (ctx->prev_in_frame)
+ av_frame_free(&ctx->prev_in_frame);
av_buffer_unref(&ctx->hw_frames_ctx);
@@ -652,49 +661,79 @@ static int deint_v4l2m2m_dequeue_frame(V4L2Queue *queue, AVFrame* frame, int tim
return 0;
}
-static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame, int field)
+static int deint_v4l2m2m_dequeue(AVFilterContext *avctx, AVFrame *input_frame)
{
DeintV4L2M2MContext *priv = avctx->priv;
DeintV4L2M2MContextShared *ctx = priv->shared;
AVFilterLink *outlink = avctx->outputs[0];
- AVFrame *output_frame;
+ AVFrame *output_frame_1, *output_frame_2;
+ int64_t first_pts = AV_NOPTS_VALUE;
int err;
- output_frame = av_frame_alloc();
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" (field %d)\n",
+ input_frame->pts, ctx->field_order);
- if (!output_frame)
+ output_frame_1 = av_frame_alloc();
+ if (!output_frame_1)
return AVERROR(ENOMEM);
- err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame, 500);
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_1, 500);
if (err < 0) {
- av_log(priv, AV_LOG_ERROR, "no frame (field %d)\n", field);
- goto fail;
+ av_log(priv, AV_LOG_ERROR, "no 1st frame (field %d)\n", ctx->field_order);
+ goto fail_out1;
}
- err = av_frame_copy_props(output_frame, input_frame);
+ err = av_frame_copy_props(output_frame_1, input_frame);
if (err < 0)
- goto fail;
+ goto fail_out1;
- output_frame->interlaced_frame = 0;
+ output_frame_1->interlaced_frame = 0;
- if (field == 0) {
- output_frame->pts *= 2;
- } else {
- int64_t cur_pts = ctx->frames[0]->pts;
- int64_t next_pts = ctx->frames[1]->pts;
+ output_frame_2 = av_frame_alloc();
+ if (!output_frame_2) {
+ err = AVERROR(ENOMEM);
+ goto fail_out1;
+ }
+
+ err = deint_v4l2m2m_dequeue_frame(&ctx->capture, output_frame_2, 500);
+ if (err < 0) {
+ av_log(priv, AV_LOG_ERROR, "no 2nd frame (field %d)\n", ctx->field_order);
+ goto fail_out2;
+ }
+
+ err = av_frame_copy_props(output_frame_2, input_frame);
+ if (err < 0)
+ goto fail_out2;
+
+ output_frame_2->interlaced_frame = 0;
- if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
- output_frame->pts = next_pts + cur_pts;
- } else {
- output_frame->pts = AV_NOPTS_VALUE;
- }
+ if (ctx->prev_in_frame && ctx->prev_in_frame->pts != AV_NOPTS_VALUE
+ && input_frame->pts != AV_NOPTS_VALUE) {
+ first_pts = (ctx->prev_in_frame->pts + input_frame->pts) / 2;
+ av_log(priv, AV_LOG_DEBUG, "calculated first pts %"PRId64"\n", first_pts);
}
- av_log(priv, AV_LOG_DEBUG, "pts: %"PRId64" (field %d)\n", output_frame->pts, field);
- return ff_filter_frame(outlink, output_frame);
+ output_frame_1->pts = first_pts;
+
+ err = ff_filter_frame(outlink, output_frame_1);
+ if (err < 0) {
+ av_frame_free(&output_frame_2);
+ return err;
+ }
+ err = ff_filter_frame(outlink, output_frame_2);
+
+ if (err < 0)
+ return err;
+
+ av_log(priv, AV_LOG_DEBUG, "1st frame pts: %"PRId64" 2nd frame pts: %"PRId64" first pts: %"PRId64" (field %d)\n",
+ output_frame_1->pts, output_frame_2->pts, first_pts, ctx->field_order);
+
+ return 0;
-fail:
- av_frame_free(&output_frame);
+fail_out2:
+ av_frame_free(&output_frame_2);
+fail_out1:
+ av_frame_free(&output_frame_1);
return err;
}
@@ -749,20 +788,22 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
V4L2Queue *output = &ctx->output;
int ret;
- av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64"\n", in->pts);
- if (!ctx->frame_count) {
+ av_log(priv, AV_LOG_DEBUG, "input pts: %"PRId64" field :%d interlaced: %d\n",
+ in->pts, in->top_field_first, in->interlaced_frame);
+
+ ctx->cur_in_frame = in;
+
+ if (ctx->field_order == V4L2_FIELD_ANY) {
AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)in->data[0];
- unsigned int field;
-
ctx->orig_width = drm_desc->layers[0].planes[0].pitch;
ctx->orig_height = drm_desc->layers[0].planes[1].offset / ctx->orig_width;
- if (in->top_field_first)
- field = V4L2_FIELD_INTERLACED_TB;
+ if (in->top_field_first)
+ ctx->field_order = V4L2_FIELD_INTERLACED_TB;
else
- field = V4L2_FIELD_INTERLACED_BT;
+ ctx->field_order = V4L2_FIELD_INTERLACED_BT;
- ret = deint_v4l2m2m_set_format(output, field, ctx->orig_width, ctx->orig_height);
+ ret = deint_v4l2m2m_set_format(output, ctx->field_order, ctx->orig_width, ctx->orig_height);
if (ret)
return ret;
@@ -787,27 +828,19 @@ static int deint_v4l2m2m_filter_frame(AVFilterLink *link, AVFrame *in)
return ret;
}
- if (ctx->frame_count < 2) {
- ctx->frames[ctx->frame_count++] = in;
- } else {
- av_frame_free(&ctx->frames[0]);
- ctx->frames[0] = ctx->frames[1];
- ctx->frames[1] = in;
- }
-
ret = deint_v4l2m2m_enqueue(output, in);
if (ret)
return ret;
- if (ctx->frame_count == 2) {
- ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 0);
- if (ret)
- return ret;
+ ret = deint_v4l2m2m_dequeue(avctx, in);
+ if (ret)
+ return ret;
- ret = deint_v4l2m2m_dequeue(avctx, ctx->frames[0], 1);
- if (ret)
- return ret;
- }
+ if (ctx->prev_in_frame)
+ av_frame_free(&ctx->prev_in_frame);
+
+ ctx->prev_in_frame = in;
+ ctx->cur_in_frame = NULL;
return 0;
}
@@ -828,6 +861,9 @@ static av_cold int deint_v4l2m2m_init(AVFilterContext *avctx)
ctx->capture.ctx = ctx;
ctx->capture.num_buffers = 6;
ctx->done = 0;
+ ctx->field_order = V4L2_FIELD_ANY;
+ ctx->cur_in_frame = NULL;
+ ctx->prev_in_frame = NULL;
atomic_init(&ctx->refcount, 1);
return 0;
--
2.29.2

View File

@ -0,0 +1,145 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 20 Oct 2019 17:10:07 +0000
Subject: [PATCH] WIP: DVDVideoCodecDRMPRIME: add support for filters
---
.../DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp | 68 ++++++++++++++++---
.../DVDCodecs/Video/DVDVideoCodecDRMPRIME.h | 10 +++
2 files changed, 69 insertions(+), 9 deletions(-)
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
index 8024c20816..7507c12e9a 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
@@ -27,6 +27,8 @@
extern "C"
{
#include <libavcodec/avcodec.h>
+#include <libavfilter/buffersink.h>
+#include <libavfilter/buffersrc.h>
#include <libavutil/error.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
@@ -525,18 +527,30 @@ void CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture)
pVideoPicture->dts = DVD_NOPTS_VALUE;
}
-CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideoPicture)
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterIn()
{
- if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
- Drain();
+ if (!m_pFilterIn)
+ return VC_PICTURE;
- if (pVideoPicture->videoBuffer)
+ int ret = av_buffersrc_add_frame(m_pFilterIn, m_pFrame);
+ if (ret < 0)
{
- pVideoPicture->videoBuffer->Release();
- pVideoPicture->videoBuffer = nullptr;
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - buffersrc add frame failed: {} ({})",
+ __FUNCTION__, err, ret);
+ return VC_ERROR;
}
- int ret = avcodec_receive_frame(m_pCodecContext, m_pFrame);
+ return ProcessFilterOut();
+}
+
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterOut()
+{
+ if (!m_pFilterOut)
+ return VC_EOF;
+
+ int ret = av_buffersink_get_frame(m_pFilterOut, m_pFrame);
if (ret == AVERROR(EAGAIN))
return VC_BUFFER;
else if (ret == AVERROR_EOF)
@@ -553,11 +567,47 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideo
{
char err[AV_ERROR_MAX_STRING_SIZE] = {};
av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
- CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - receive frame failed: {} ({})", __FUNCTION__,
- err, ret);
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - buffersink get frame failed: {} ({})",
+ __FUNCTION__, err, ret);
return VC_ERROR;
}
+ return VC_PICTURE;
+}
+
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideoPicture)
+{
+ if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
+ Drain();
+
+ if (pVideoPicture->videoBuffer)
+ {
+ pVideoPicture->videoBuffer->Release();
+ pVideoPicture->videoBuffer = nullptr;
+ }
+
+ auto result = ProcessFilterOut();
+ if (result != VC_PICTURE)
+ {
+ int ret = avcodec_receive_frame(m_pCodecContext, m_pFrame);
+ if (ret == AVERROR(EAGAIN))
+ return VC_BUFFER;
+ else if (ret == AVERROR_EOF)
+ return VC_EOF;
+ else if (ret)
+ {
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - receive frame failed: {} ({})",
+ __FUNCTION__, err, ret);
+ return VC_ERROR;
+ }
+
+ result = ProcessFilterIn();
+ if (result != VC_PICTURE)
+ return result;
+ }
+
SetPictureParams(pVideoPicture);
if (IsSupportedHwFormat(static_cast<AVPixelFormat>(m_pFrame->format)))
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
index 77d066c3d9..7112d1b48a 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
@@ -14,6 +14,11 @@
#include <memory>
+extern "C"
+{
+#include <libavfilter/avfilter.h>
+}
+
class CDVDVideoCodecDRMPRIME : public CDVDVideoCodec
{
public:
@@ -35,6 +40,8 @@ protected:
void Drain();
void SetPictureParams(VideoPicture* pVideoPicture);
void UpdateProcessInfo(struct AVCodecContext* avctx, const enum AVPixelFormat fmt);
+ CDVDVideoCodec::VCReturn ProcessFilterIn();
+ CDVDVideoCodec::VCReturn ProcessFilterOut();
static enum AVPixelFormat GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt);
static int GetBuffer(struct AVCodecContext* avctx, AVFrame* frame, int flags);
@@ -43,5 +50,8 @@ protected:
CDVDStreamInfo m_hints;
AVCodecContext* m_pCodecContext = nullptr;
AVFrame* m_pFrame = nullptr;
+ AVFilterGraph* m_pFilterGraph = nullptr;
+ AVFilterContext* m_pFilterIn = nullptr;
+ AVFilterContext* m_pFilterOut = nullptr;
std::shared_ptr<IVideoBufferPool> m_videoBufferPool;
};

View File

@ -0,0 +1,500 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Thu, 26 Dec 2019 11:01:51 +0100
Subject: [PATCH] WIP: DRMPRIME deinterlace filter
---
.../DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp | 368 +++++++++++++++---
.../DVDCodecs/Video/DVDVideoCodecDRMPRIME.h | 9 +-
2 files changed, 322 insertions(+), 55 deletions(-)
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
index 7507c12e9a..4759dde3f9 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.cpp
@@ -79,12 +79,15 @@ CDVDVideoCodecDRMPRIME::CDVDVideoCodecDRMPRIME(CProcessInfo& processInfo)
: CDVDVideoCodec(processInfo)
{
m_pFrame = av_frame_alloc();
+ m_pFilterFrame = av_frame_alloc();
m_videoBufferPool = std::make_shared<CVideoBufferPoolDRMPRIMEFFmpeg>();
}
CDVDVideoCodecDRMPRIME::~CDVDVideoCodecDRMPRIME()
{
av_frame_free(&m_pFrame);
+ av_frame_free(&m_pFilterFrame);
+ FilterClose();
avcodec_free_context(&m_pCodecContext);
}
@@ -341,8 +344,19 @@ bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& optio
}
UpdateProcessInfo(m_pCodecContext, m_pCodecContext->pix_fmt);
- m_processInfo.SetVideoDeintMethod("none");
+ m_processInfo.SetVideoInterlaced(false);
m_processInfo.SetVideoDAR(hints.aspect);
+ m_processInfo.SetVideoDeintMethod("none");
+
+ FilterTest();
+
+ if (!m_deintFilterName.empty())
+ {
+ std::list<EINTERLACEMETHOD> methods;
+ methods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE);
+ m_processInfo.UpdateDeinterlacingMethods(methods);
+ m_processInfo.SetDeinterlacingMethodDefault(EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE);
+ }
return true;
}
@@ -405,6 +419,8 @@ void CDVDVideoCodecDRMPRIME::Reset()
return;
Drain();
+ m_filters.clear();
+ FilterClose();
do
{
@@ -443,7 +459,7 @@ void CDVDVideoCodecDRMPRIME::Drain()
}
}
-void CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture)
+bool CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture)
{
pVideoPicture->iWidth = m_pFrame->width;
pVideoPicture->iHeight = m_pFrame->height;
@@ -525,13 +541,232 @@ void CDVDVideoCodecDRMPRIME::SetPictureParams(VideoPicture* pVideoPicture)
? DVD_NOPTS_VALUE
: static_cast<double>(pts) * DVD_TIME_BASE / AV_TIME_BASE;
pVideoPicture->dts = DVD_NOPTS_VALUE;
+
+ if (IsSupportedHwFormat(static_cast<AVPixelFormat>(m_pFrame->format)))
+ {
+ CVideoBufferDRMPRIMEFFmpeg* buffer =
+ dynamic_cast<CVideoBufferDRMPRIMEFFmpeg*>(m_videoBufferPool->Get());
+ buffer->SetPictureParams(*pVideoPicture);
+ buffer->SetRef(m_pFrame);
+ pVideoPicture->videoBuffer = buffer;
+ }
+ else if (m_pFrame->opaque)
+ {
+ CVideoBufferDMA* buffer = static_cast<CVideoBufferDMA*>(m_pFrame->opaque);
+ buffer->SetPictureParams(*pVideoPicture);
+ buffer->Acquire();
+ buffer->SyncEnd();
+ buffer->SetDimensions(m_pFrame->width, m_pFrame->height);
+
+ pVideoPicture->videoBuffer = buffer;
+ av_frame_unref(m_pFrame);
+ }
+
+ if (!pVideoPicture->videoBuffer)
+ {
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - videoBuffer:nullptr format:{}", __FUNCTION__,
+ av_get_pix_fmt_name(static_cast<AVPixelFormat>(m_pFrame->format)));
+ av_frame_unref(m_pFrame);
+ return false;
+ }
+
+ return true;
}
-CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterIn()
+void CDVDVideoCodecDRMPRIME::FilterTest()
+{
+ const AVFilter* filter;
+ void* opaque{};
+
+ m_deintFilterName.clear();
+
+ while ((filter = av_filter_iterate(&opaque)) != nullptr)
+ {
+ std::string name(filter->name);
+
+ if (name.find("deinterlace") != std::string::npos)
+ {
+ if (FilterOpen(name, true))
+ {
+ m_deintFilterName = name;
+
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::{} - found deinterlacing filter {}",
+ __FUNCTION__, name);
+
+ return;
+ }
+ }
+ }
+
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::{} - no deinterlacing filter found",
+ __FUNCTION__);
+}
+
+bool CDVDVideoCodecDRMPRIME::FilterOpen(const std::string& filters, bool test)
+{
+ int result;
+
+ if (m_pFilterGraph)
+ FilterClose();
+
+ if (filters.empty())
+ return true;
+
+ if (!(m_pFilterGraph = avfilter_graph_alloc()))
+ {
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - unable to alloc filter graph");
+ return false;
+ }
+
+ const AVFilter* srcFilter = avfilter_get_by_name("buffer");
+ const AVFilter* outFilter = avfilter_get_by_name("buffersink");
+ enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_DRM_PRIME, AV_PIX_FMT_NONE };
+
+ std::string args = StringUtils::Format("video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:"
+ "pixel_aspect=%d/%d:sws_param=flags=2",
+ m_pCodecContext->width,
+ m_pCodecContext->height,
+ m_pCodecContext->pix_fmt,
+ m_pCodecContext->time_base.num ?
+ m_pCodecContext->time_base.num : 1,
+ m_pCodecContext->time_base.num ?
+ m_pCodecContext->time_base.den : 1,
+ m_pCodecContext->sample_aspect_ratio.num != 0 ?
+ m_pCodecContext->sample_aspect_ratio.num : 1,
+ m_pCodecContext->sample_aspect_ratio.num != 0 ?
+ m_pCodecContext->sample_aspect_ratio.den : 1);
+
+ result = avfilter_graph_create_filter(&m_pFilterIn, srcFilter, "src",
+ args.c_str(), NULL, m_pFilterGraph);
+ if (result < 0)
+ {
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(result, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGERROR,
+ "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_create_filter: src: {} ({})",
+ err, result);
+ return false;
+ }
+
+ AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
+ if (!par)
+ {
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - unable to alloc buffersrc");
+ return false;
+ }
+
+ memset(par, 0, sizeof(*par));
+ par->format = AV_PIX_FMT_NONE;
+ par->hw_frames_ctx = m_pCodecContext->hw_device_ctx;
+
+ result = av_buffersrc_parameters_set(m_pFilterIn, par);
+ if (result < 0)
+ {
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(result, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGERROR,
+ "CDVDVideoCodecDRMPRIME::FilterOpen - av_buffersrc_parameters_set: {} ({})",
+ err, result);
+ return false;
+ }
+ av_freep(&par);
+
+ result = avfilter_graph_create_filter(&m_pFilterOut, outFilter, "out",
+ NULL, NULL, m_pFilterGraph);
+ if (result < 0)
+ {
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(result, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGERROR,
+ "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_create_filter: out: {} ({})",
+ err, result);
+ return false;
+ }
+
+ result = av_opt_set_int_list(m_pFilterOut, "pix_fmts", &pix_fmts[0],
+ AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
+ if (result < 0)
+ {
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - failed settings pix formats");
+ return false;
+ }
+
+ AVFilterInOut* outputs = avfilter_inout_alloc();
+ AVFilterInOut* inputs = avfilter_inout_alloc();
+
+ outputs->name = av_strdup("in");
+ outputs->filter_ctx = m_pFilterIn;
+ outputs->pad_idx = 0;
+ outputs->next = nullptr;
+
+ inputs->name = av_strdup("out");
+ inputs->filter_ctx = m_pFilterOut;
+ inputs->pad_idx = 0;
+ inputs->next = nullptr;
+
+ result = avfilter_graph_parse_ptr(m_pFilterGraph, filters.c_str(), &inputs, &outputs, NULL);
+ avfilter_inout_free(&outputs);
+ avfilter_inout_free(&inputs);
+
+ if (result < 0)
+ {
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_parse");
+ return false;
+ }
+
+ if ((result = avfilter_graph_config(m_pFilterGraph, nullptr)) < 0)
+ {
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(result, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::FilterOpen - avfilter_graph_config: {} ({})",
+ err, result);
+ return false;
+ }
+
+ if (test)
+ {
+ FilterClose();
+ return true;
+ }
+
+ if (filters.find("deinterlace") != std::string::npos)
+ {
+ m_processInfo.SetVideoDeintMethod(filters);
+ }
+ else
+ {
+ m_processInfo.SetVideoDeintMethod("none");
+ }
+
+ if (CServiceBroker::GetLogging().CanLogComponent(LOGVIDEO))
+ {
+ char* graphDump = avfilter_graph_dump(m_pFilterGraph, nullptr);
+ if (graphDump)
+ {
+ CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::FilterOpen - Final filter graph:\n%s",
+ graphDump);
+ av_freep(&graphDump);
+ }
+ }
+
+ return true;
+}
+
+void CDVDVideoCodecDRMPRIME::FilterClose()
{
- if (!m_pFilterIn)
- return VC_PICTURE;
+ if (m_pFilterGraph)
+ {
+ CLog::Log(LOGDEBUG, LOGVIDEO, "CDVDVideoCodecDRMPRIME::FilterClose - Freeing filter graph");
+ avfilter_graph_free(&m_pFilterGraph);
+
+ // Disposed by above code
+ m_pFilterIn = nullptr;
+ m_pFilterOut = nullptr;
+ }
+}
+CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterIn()
+{
int ret = av_buffersrc_add_frame(m_pFilterIn, m_pFrame);
if (ret < 0)
{
@@ -547,21 +782,14 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterIn()
CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterOut()
{
- if (!m_pFilterOut)
- return VC_EOF;
-
- int ret = av_buffersink_get_frame(m_pFilterOut, m_pFrame);
+ int ret = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame);
if (ret == AVERROR(EAGAIN))
return VC_BUFFER;
else if (ret == AVERROR_EOF)
{
- if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
- {
- CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::{} - flush buffers", __FUNCTION__);
- avcodec_flush_buffers(m_pCodecContext);
- SetCodecControl(m_codecControlFlags & ~DVD_CODEC_CTRL_DRAIN);
- }
- return VC_EOF;
+ ret = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame);
+ if (ret < 0)
+ return VC_BUFFER;
}
else if (ret)
{
@@ -572,9 +800,27 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::ProcessFilterOut()
return VC_ERROR;
}
+ av_frame_unref(m_pFrame);
+ av_frame_move_ref(m_pFrame, m_pFilterFrame);
+
return VC_PICTURE;
}
+std::string CDVDVideoCodecDRMPRIME::GetFilterChain(bool interlaced)
+{
+ // ask codec to do deinterlacing if possible
+ EINTERLACEMETHOD mInt = m_processInfo.GetVideoSettings().m_InterlaceMethod;
+ std::string filterChain;
+
+ if (!m_processInfo.Supports(mInt))
+ mInt = m_processInfo.GetFallbackDeintMethod();
+
+ if (mInt != VS_INTERLACEMETHOD_NONE && interlaced && !m_deintFilterName.empty())
+ filterChain += m_deintFilterName;
+
+ return filterChain;
+}
+
CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideoPicture)
{
if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
@@ -586,57 +832,71 @@ CDVDVideoCodec::VCReturn CDVDVideoCodecDRMPRIME::GetPicture(VideoPicture* pVideo
pVideoPicture->videoBuffer = nullptr;
}
- auto result = ProcessFilterOut();
- if (result != VC_PICTURE)
+ if (m_pFilterGraph)
{
- int ret = avcodec_receive_frame(m_pCodecContext, m_pFrame);
- if (ret == AVERROR(EAGAIN))
- return VC_BUFFER;
- else if (ret == AVERROR_EOF)
- return VC_EOF;
- else if (ret)
+ auto ret = ProcessFilterOut();
+ if (ret == VC_PICTURE)
{
- char err[AV_ERROR_MAX_STRING_SIZE] = {};
- av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
- CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - receive frame failed: {} ({})",
- __FUNCTION__, err, ret);
- return VC_ERROR;
+ if (!SetPictureParams(pVideoPicture))
+ return VC_ERROR;
+ return VC_PICTURE;
}
+ else if (ret != VC_BUFFER)
+ {
+ return ret;
+ }
+ }
- result = ProcessFilterIn();
- if (result != VC_PICTURE)
- return result;
+ int ret = avcodec_receive_frame(m_pCodecContext, m_pFrame);
+ if (ret == AVERROR(EAGAIN))
+ return VC_BUFFER;
+ else if (ret == AVERROR_EOF)
+ return VC_EOF;
+ else if (ret)
+ {
+ char err[AV_ERROR_MAX_STRING_SIZE] = {};
+ av_strerror(ret, err, AV_ERROR_MAX_STRING_SIZE);
+ CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - receive frame failed: {} ({})",
+ __FUNCTION__, err, ret);
+ return VC_ERROR;
}
- SetPictureParams(pVideoPicture);
+ if (!m_processInfo.GetVideoInterlaced() && m_pFrame->interlaced_frame)
+ m_processInfo.SetVideoInterlaced(true);
- if (IsSupportedHwFormat(static_cast<AVPixelFormat>(m_pFrame->format)))
+ std::string filterChain = GetFilterChain(m_pFrame->interlaced_frame);
+ if (!filterChain.empty())
{
- CVideoBufferDRMPRIMEFFmpeg* buffer =
- dynamic_cast<CVideoBufferDRMPRIMEFFmpeg*>(m_videoBufferPool->Get());
- buffer->SetPictureParams(*pVideoPicture);
- buffer->SetRef(m_pFrame);
- pVideoPicture->videoBuffer = buffer;
+ bool reopenFilter = false;
+ if (m_filters != filterChain)
+ reopenFilter = true;
+
+ if (m_pFilterGraph &&
+ (m_pFilterIn->outputs[0]->w != m_pCodecContext->width ||
+ m_pFilterIn->outputs[0]->h != m_pCodecContext->height))
+ reopenFilter = true;
+
+ if (reopenFilter)
+ {
+ m_filters = filterChain;
+ if (!FilterOpen(filterChain, false))
+ FilterClose();
+ }
+
+ if (m_pFilterGraph)
+ {
+ if (ProcessFilterIn() != VC_PICTURE)
+ return VC_NONE;
+ }
}
- else if (m_pFrame->opaque)
+ else
{
- CVideoBufferDMA* buffer = static_cast<CVideoBufferDMA*>(m_pFrame->opaque);
- buffer->SetPictureParams(*pVideoPicture);
- buffer->Acquire();
- buffer->SyncEnd();
- buffer->SetDimensions(m_pFrame->width, m_pFrame->height);
-
- pVideoPicture->videoBuffer = buffer;
- av_frame_unref(m_pFrame);
+ m_filters.clear();
+ FilterClose();
}
- if (!pVideoPicture->videoBuffer)
- {
- CLog::Log(LOGERROR, "CDVDVideoCodecDRMPRIME::{} - videoBuffer:nullptr format:{}", __FUNCTION__,
- av_get_pix_fmt_name(static_cast<AVPixelFormat>(m_pFrame->format)));
- av_frame_unref(m_pFrame);
+ if (!SetPictureParams(pVideoPicture))
return VC_ERROR;
- }
return VC_PICTURE;
}
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
index 7112d1b48a..13bec95135 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecDRMPRIME.h
@@ -38,18 +38,25 @@ public:
protected:
void Drain();
- void SetPictureParams(VideoPicture* pVideoPicture);
+ bool SetPictureParams(VideoPicture* pVideoPicture);
void UpdateProcessInfo(struct AVCodecContext* avctx, const enum AVPixelFormat fmt);
CDVDVideoCodec::VCReturn ProcessFilterIn();
CDVDVideoCodec::VCReturn ProcessFilterOut();
static enum AVPixelFormat GetFormat(struct AVCodecContext* avctx, const enum AVPixelFormat* fmt);
static int GetBuffer(struct AVCodecContext* avctx, AVFrame* frame, int flags);
+ bool FilterOpen(const std::string& filters, bool test);
+ void FilterClose();
+ void FilterTest();
+ std::string GetFilterChain(bool interlaced);
std::string m_name;
+ std::string m_deintFilterName;
+ std::string m_filters;
int m_codecControlFlags = 0;
CDVDStreamInfo m_hints;
AVCodecContext* m_pCodecContext = nullptr;
AVFrame* m_pFrame = nullptr;
+ AVFrame* m_pFilterFrame = nullptr;
AVFilterGraph* m_pFilterGraph = nullptr;
AVFilterContext* m_pFilterIn = nullptr;
AVFilterContext* m_pFilterOut = nullptr;

View File

@ -232,3 +232,456 @@ index 80053d91a301..2c55e1852c3d 100644
.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Qinglang Miao <miaoqinglang@huawei.com>
Date: Tue, 1 Dec 2020 20:54:57 +0800
Subject: [PATCH] drm/rockchip: cdn-dp: fix reference leak when
pm_runtime_get_sync fails
The PM reference count is not expected to be incremented on
return in cdn_dp_clk_enable.
However, pm_runtime_get_sync will increment the PM reference
count even failed. Forgetting to putting operation will result
in a reference leak here.
Replace it with pm_runtime_resume_and_get to keep usage
counter balanced.
Fixes: efe0220fc2d2 ("drm/rockchip: cdn-dp: Fix error handling")
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
---
drivers/gpu/drm/rockchip/cdn-dp-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index a4a45daf93f2..9b4406191470 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -98,7 +98,7 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
goto err_core_clk;
}
- ret = pm_runtime_get_sync(dp->dev);
+ ret = pm_runtime_resume_and_get(dp->dev);
if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "cannot get pm runtime %d\n", ret);
goto err_pm_runtime_get;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Qinglang Miao <miaoqinglang@huawei.com>
Date: Tue, 1 Dec 2020 20:54:58 +0800
Subject: [PATCH] drm/rockchip: vop: fix reference leak when
pm_runtime_get_sync fails
The PM reference count is not expected to be incremented on
return in functions vop_enable and vop_enable.
However, pm_runtime_get_sync will increment the PM reference
count even failed. Forgetting to putting operation will result
in a reference leak here.
Replace it with pm_runtime_resume_and_get to keep usage
counter balanced.
Fixes: 5e570373c015 ("drm/rockchip: vop: Enable pm domain before vop_initial")
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index eb663e25ad9e..c6c76e8ab66c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -602,7 +602,7 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
struct vop *vop = to_vop(crtc);
int ret, i;
- ret = pm_runtime_get_sync(vop->dev);
+ ret = pm_runtime_resume_and_get(vop->dev);
if (ret < 0) {
DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);
return ret;
@@ -1933,7 +1933,7 @@ static int vop_initial(struct vop *vop)
return PTR_ERR(vop->dclk);
}
- ret = pm_runtime_get_sync(vop->dev);
+ ret = pm_runtime_resume_and_get(vop->dev);
if (ret < 0) {
DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);
return ret;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Qinglang Miao <miaoqinglang@huawei.com>
Date: Tue, 1 Dec 2020 20:54:59 +0800
Subject: [PATCH] drm/rockchip: lvds: fix reference leak when
pm_runtime_get_sync fails
The PM reference count is not expected to be incremented on
return in functions rk3288_lvds_poweron and px30_lvds_poweron.
However, pm_runtime_get_sync will increment the PM reference
count even failed. Forgetting to putting operation will result
in a reference leak here.
Replace it with pm_runtime_resume_and_get to keep usage
counter balanced.
Fixes: cca1705c3d89 ("drm/rockchip: lvds: Add PX30 support")
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
---
drivers/gpu/drm/rockchip/rockchip_lvds.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 41edd0a421b2..4d463d50a63a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -145,7 +145,7 @@ static int rk3288_lvds_poweron(struct rockchip_lvds *lvds)
DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret);
return ret;
}
- ret = pm_runtime_get_sync(lvds->dev);
+ ret = pm_runtime_resume_and_get(lvds->dev);
if (ret < 0) {
DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
clk_disable(lvds->pclk);
@@ -329,7 +329,7 @@ static int px30_lvds_poweron(struct rockchip_lvds *lvds)
{
int ret;
- ret = pm_runtime_get_sync(lvds->dev);
+ ret = pm_runtime_resume_and_get(lvds->dev);
if (ret < 0) {
DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
return ret;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lukasz Luba <lukasz.luba@arm.com>
Date: Tue, 5 Jan 2021 16:41:11 +0000
Subject: [PATCH] drm/panfrost: Use delayed timer as default in devfreq profile
Devfreq framework supports 2 modes for monitoring devices.
Use delayed timer as default instead of deferrable timer
in order to monitor the GPU status regardless of CPU idle.
Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Steven Price <steven.price@arm.com>
---
drivers/gpu/drm/panfrost/panfrost_devfreq.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index 913eaa6d0bc6..17d5fa6e0b83 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -76,6 +76,7 @@ static int panfrost_devfreq_get_dev_status(struct device *dev,
}
static struct devfreq_dev_profile panfrost_devfreq_profile = {
+ .timer = DEVFREQ_TIMER_DELAYED,
.polling_ms = 50, /* ~3 frames */
.target = panfrost_devfreq_target,
.get_dev_status = panfrost_devfreq_get_dev_status,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lukasz Luba <lukasz.luba@arm.com>
Date: Thu, 21 Jan 2021 17:04:45 +0000
Subject: [PATCH] drm/panfrost: Add governor data with pre-defined thresholds
The simple_ondemand devfreq governor uses two thresholds to decide about
the frequency change: upthreshold, downdifferential. These two tunable
change the behavior of the governor decision, e.g. how fast to increase
the frequency or how rapidly limit the frequency. This patch adds needed
governor data with thresholds values gathered experimentally in different
workloads.
Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
---
drivers/gpu/drm/panfrost/panfrost_devfreq.c | 10 +++++++++-
drivers/gpu/drm/panfrost/panfrost_devfreq.h | 2 ++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
index 17d5fa6e0b83..53e0188ce8e8 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -130,8 +130,16 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
panfrost_devfreq_profile.initial_freq = cur_freq;
dev_pm_opp_put(opp);
+ /*
+ * Setup default thresholds for the simple_ondemand governor.
+ * The values are chosen based on experiments.
+ */
+ pfdevfreq->gov_data.upthreshold = 45;
+ pfdevfreq->gov_data.downdifferential = 5;
+
devfreq = devm_devfreq_add_device(dev, &panfrost_devfreq_profile,
- DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
+ DEVFREQ_GOV_SIMPLE_ONDEMAND,
+ &pfdevfreq->gov_data);
if (IS_ERR(devfreq)) {
DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n");
ret = PTR_ERR(devfreq);
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h
index db6ea48e21f9..1e2a4de941aa 100644
--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h
+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h
@@ -4,6 +4,7 @@
#ifndef __PANFROST_DEVFREQ_H__
#define __PANFROST_DEVFREQ_H__
+#include <linux/devfreq.h>
#include <linux/spinlock.h>
#include <linux/ktime.h>
@@ -17,6 +18,7 @@ struct panfrost_devfreq {
struct devfreq *devfreq;
struct opp_table *regulators_opp_table;
struct thermal_cooling_device *cooling;
+ struct devfreq_simple_ondemand_data gov_data;
bool opp_of_table_added;
ktime_t busy_time;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Fri, 5 Feb 2021 12:17:55 +0100
Subject: [PATCH] drm/panfrost: Clear MMU irqs before handling the fault
When a fault is handled it will unblock the GPU which will continue
executing its shader and might fault almost immediately on a different
page. If we clear interrupts after handling the fault we might miss new
faults, so clear them before.
Cc: <stable@vger.kernel.org>
Fixes: 187d2929206e ("drm/panfrost: Add support for GPU heap allocations")
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
---
drivers/gpu/drm/panfrost/panfrost_mmu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index be8d68fb0e11..e5f7f647430f 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -600,6 +600,8 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
access_type = (fault_status >> 8) & 0x3;
source_id = (fault_status >> 16);
+ mmu_write(pfdev, MMU_INT_CLEAR, mask);
+
/* Page fault only */
ret = -1;
if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
@@ -623,8 +625,6 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
access_type, access_type_name(pfdev, fault_status),
source_id);
- mmu_write(pfdev, MMU_INT_CLEAR, mask);
-
status &= ~mask;
}
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Fri, 5 Feb 2021 12:17:56 +0100
Subject: [PATCH] drm/panfrost: Don't try to map pages that are already mapped
We allocate 2MB chunks at a time, so it might appear that a page fault
has already been handled by a previous page fault when we reach
panfrost_mmu_map_fault_addr(). Bail out in that case to avoid mapping the
same area twice.
Cc: <stable@vger.kernel.org>
Fixes: 187d2929206e ("drm/panfrost: Add support for GPU heap allocations")
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
---
drivers/gpu/drm/panfrost/panfrost_mmu.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index e5f7f647430f..198686216317 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -495,8 +495,14 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
}
bo->base.pages = pages;
bo->base.pages_use_count = 1;
- } else
+ } else {
pages = bo->base.pages;
+ if (pages[page_offset]) {
+ /* Pages are already mapped, bail out. */
+ mutex_unlock(&bo->base.pages_lock);
+ goto out;
+ }
+ }
mapping = bo->base.base.filp->f_mapping;
mapping_set_unevictable(mapping);
@@ -529,6 +535,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr);
+out:
panfrost_gem_mapping_put(bomapping);
return 0;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Fri, 5 Feb 2021 12:17:57 +0100
Subject: [PATCH] drm/panfrost: Stay in the threaded MMU IRQ handler until
we've handled all IRQs
Doing a hw-irq -> threaded-irq round-trip is counter-productive, stay
in the threaded irq handler as long as we can.
v2:
* Rework the loop to avoid a goto
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
drivers/gpu/drm/panfrost/panfrost_mmu.c | 26 +++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 198686216317..5a3d18c05802 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -585,22 +585,20 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
{
struct panfrost_device *pfdev = data;
u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT);
- int i, ret;
+ int ret;
- for (i = 0; status; i++) {
- u32 mask = BIT(i) | BIT(i + 16);
+ while (status) {
+ u32 as = ffs(status | (status >> 16)) - 1;
+ u32 mask = BIT(as) | BIT(as + 16);
u64 addr;
u32 fault_status;
u32 exception_type;
u32 access_type;
u32 source_id;
- if (!(status & mask))
- continue;
-
- fault_status = mmu_read(pfdev, AS_FAULTSTATUS(i));
- addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(i));
- addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(i)) << 32;
+ fault_status = mmu_read(pfdev, AS_FAULTSTATUS(as));
+ addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(as));
+ addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(as)) << 32;
/* decode the fault status */
exception_type = fault_status & 0xFF;
@@ -611,8 +609,8 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
/* Page fault only */
ret = -1;
- if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
- ret = panfrost_mmu_map_fault_addr(pfdev, i, addr);
+ if ((status & mask) == BIT(as) && (exception_type & 0xF8) == 0xC0)
+ ret = panfrost_mmu_map_fault_addr(pfdev, as, addr);
if (ret)
/* terminal fault, print info about the fault */
@@ -624,7 +622,7 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
"exception type 0x%X: %s\n"
"access type 0x%X: %s\n"
"source id 0x%X\n",
- i, addr,
+ as, addr,
"TODO",
fault_status,
(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
@@ -633,6 +631,10 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
source_id);
status &= ~mask;
+
+ /* If we received new MMU interrupts, process them before returning. */
+ if (!status)
+ status = mmu_read(pfdev, MMU_INT_RAWSTAT);
}
mmu_write(pfdev, MMU_INT_MASK, ~0);
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Christian Hewitt <christianshewitt@gmail.com>
Date: Wed, 27 Jan 2021 19:40:47 +0000
Subject: [PATCH] drm/lima: add governor data with pre-defined thresholds
This patch adapts the panfrost pre-defined thresholds change [0] to the
lima driver to improve real-world performance. The upthreshold value has
been set to ramp GPU frequency to max freq faster (compared to panfrost)
to compensate for the lower overall performance of utgard devices.
[0] https://patchwork.kernel.org/project/dri-devel/patch/20210121170445.19761-1-lukasz.luba@arm.com/
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Qiang Yu <yuq825@gmail.com>
---
drivers/gpu/drm/lima/lima_devfreq.c | 10 +++++++++-
drivers/gpu/drm/lima/lima_devfreq.h | 2 ++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c
index 5686ad4aaf7c..c9854315a0b5 100644
--- a/drivers/gpu/drm/lima/lima_devfreq.c
+++ b/drivers/gpu/drm/lima/lima_devfreq.c
@@ -163,8 +163,16 @@ int lima_devfreq_init(struct lima_device *ldev)
lima_devfreq_profile.initial_freq = cur_freq;
dev_pm_opp_put(opp);
+ /*
+ * Setup default thresholds for the simple_ondemand governor.
+ * The values are chosen based on experiments.
+ */
+ ldevfreq->gov_data.upthreshold = 30;
+ ldevfreq->gov_data.downdifferential = 5;
+
devfreq = devm_devfreq_add_device(dev, &lima_devfreq_profile,
- DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
+ DEVFREQ_GOV_SIMPLE_ONDEMAND,
+ &ldevfreq->gov_data);
if (IS_ERR(devfreq)) {
dev_err(dev, "Couldn't initialize GPU devfreq\n");
ret = PTR_ERR(devfreq);
diff --git a/drivers/gpu/drm/lima/lima_devfreq.h b/drivers/gpu/drm/lima/lima_devfreq.h
index 2d9b3008ce77..b0c7c736e81a 100644
--- a/drivers/gpu/drm/lima/lima_devfreq.h
+++ b/drivers/gpu/drm/lima/lima_devfreq.h
@@ -4,6 +4,7 @@
#ifndef __LIMA_DEVFREQ_H__
#define __LIMA_DEVFREQ_H__
+#include <linux/devfreq.h>
#include <linux/spinlock.h>
#include <linux/ktime.h>
@@ -18,6 +19,7 @@ struct lima_devfreq {
struct opp_table *clkname_opp_table;
struct opp_table *regulators_opp_table;
struct thermal_cooling_device *cooling;
+ struct devfreq_simple_ondemand_data gov_data;
ktime_t busy_time;
ktime_t idle_time;

View File

@ -1,76 +0,0 @@
From e7cc7e8e0812ce96035ad1d286d79a37f3ea81d2 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 16 Jan 2021 12:24:58 +0000
Subject: [PATCH] ARM64: dts: rockchip: RK3328: enable USB3 for supported
boards
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328-a1.dts | 21 +++++++++++++++++++
.../arm64/boot/dts/rockchip/rk3328-rock64.dts | 21 +++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
index 37f307cfa4cc..4013f16bb368 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
@@ -352,6 +352,27 @@ &usb_host0_ehci {
status = "okay";
};
+&usbdrd3 {
+ status = "okay";
+};
+
+&usbdrd_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb3phy {
+ status = "okay";
+};
+
+&usb3phy_utmi {
+ status = "okay";
+};
+
+&usb3phy_pipe {
+ status = "okay";
+};
+
&vop {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
index c984662043da..89fde87f7650 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -384,6 +384,27 @@ &usb_host0_ohci {
status = "okay";
};
+&usbdrd3 {
+ status = "okay";
+};
+
+&usbdrd_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb3phy {
+ status = "okay";
+};
+
+&usb3phy_utmi {
+ status = "okay";
+};
+
+&usb3phy_pipe {
+ status = "okay";
+};
+
&vop {
status = "okay";
};

View File

@ -0,0 +1,452 @@
From e7cc7e8e0812ce96035ad1d286d79a37f3ea81d2 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 16 Jan 2021 12:24:58 +0000
Subject: [PATCH] ARM64: dts: rockchip: RK3328: enable USB3 for supported
boards
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328-a1.dts | 21 +++++++++++++++++++
.../arm64/boot/dts/rockchip/rk3328-rock64.dts | 21 +++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
index 37f307cfa4cc..4013f16bb368 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-a1.dts
@@ -352,6 +352,27 @@ &usb_host0_ehci {
status = "okay";
};
+&usbdrd3 {
+ status = "okay";
+};
+
+&usbdrd_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb3phy {
+ status = "okay";
+};
+
+&usb3phy_utmi {
+ status = "okay";
+};
+
+&usb3phy_pipe {
+ status = "okay";
+};
+
&vop {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
index c984662043da..89fde87f7650 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -384,6 +384,27 @@ &usb_host0_ohci {
status = "okay";
};
+&usbdrd3 {
+ status = "okay";
+};
+
+&usbdrd_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb3phy {
+ status = "okay";
+};
+
+&usb3phy_utmi {
+ status = "okay";
+};
+
+&usb3phy_pipe {
+ status = "okay";
+};
+
&vop {
status = "okay";
};
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 2 Sep 2020 19:52:02 +0200
Subject: [PATCH] arm64: dts: rockchip: add gpu powerdomain, gpu opp-table and
cooling cell
Note: since the regulator that supplies the GPU usually also supplies
other SoC components, we have to make sure voltage is never lower then
1050 mV.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 33 ++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index b54ff9055e5f..2fae7fa6b000 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -321,6 +321,10 @@ power: power-controller {
#address-cells = <1>;
#size-cells = <0>;
+ pd_gpu@RK3328_PD_GPU {
+ reg = <RK3328_PD_GPU>;
+ clocks = <&cru ACLK_GPU>;
+ };
pd_hevc@RK3328_PD_HEVC {
reg = <RK3328_PD_HEVC>;
};
@@ -546,6 +550,11 @@ map0 {
<&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
contribution = <4096>;
};
+ map1 {
+ trip = <&target>;
+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ contribution = <4096>;
+ };
};
};
@@ -627,7 +636,31 @@ gpu: gpu@ff300000 {
"ppmmu1";
clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>;
clock-names = "bus", "core";
+ operating-points-v2 = <&gpu_opp_table>;
+ power-domains = <&power RK3328_PD_GPU>;
resets = <&cru SRST_GPU_A>;
+ #cooling-cells = <2>;
+ };
+
+ gpu_opp_table: gpu-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <1050000>;
+ };
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <1050000>;
+ };
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <1050000>;
+ };
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <1150000>;
+ };
};
h265e_mmu: iommu@ff330200 {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 2 Sep 2020 21:22:31 +0200
Subject: [PATCH] arm64: dts: rockchip: add rockchip,disable-mmu-reset for vdec
iommu
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 2fae7fa6b000..3d933d74c2b3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -731,6 +731,7 @@ rkvdec_mmu: iommu@ff360480 {
clock-names = "aclk", "iface";
#iommu-cells = <0>;
power-domains = <&power RK3328_PD_VIDEO>;
+ rockchip,disable-mmu-reset;
};
vop: vop@ff370000 {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Mon, 10 Feb 2020 19:22:41 +0100
Subject: [PATCH] ARM64: dts: rk3328 add sdmmc ext node
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 3d933d74c2b3..bd1e5edfbf95 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -1104,6 +1104,20 @@ usbdrd_dwc3: dwc3@ff600000 {
};
};
+ sdmmc_ext: dwmmc@ff5f0000 {
+ compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0x0 0xff5f0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_SDMMC_EXT>, <&cru SCLK_SDMMC_EXT>,
+ <&cru SCLK_SDMMC_EXT_DRV>, <&cru SCLK_SDMMC_EXT_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <150000000>;
+ resets = <&cru SRST_SDMMCEXT>;
+ reset-names = "reset";
+ status = "disabled";
+ };
+
gic: interrupt-controller@ff811000 {
compatible = "arm,gic-400";
#interrupt-cells = <3>;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Tue, 2 Feb 2021 17:22:21 +0200
Subject: [PATCH] arm: dts: rk3288 miqi add hdmi sound nodes
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm/boot/dts/rk3288-miqi.dts | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts
index 713f55e143c6..2420d8e1c66f 100644
--- a/arch/arm/boot/dts/rk3288-miqi.dts
+++ b/arch/arm/boot/dts/rk3288-miqi.dts
@@ -78,6 +78,21 @@ vcc_sys: vsys-regulator {
regulator-always-on;
regulator-boot-on;
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "rockchip,miqi-codec";
+ simple-audio-card,mclk-fs = <512>;
+
+ simple-audio-card,codec {
+ sound-dai = <&hdmi>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s>;
+ };
+ };
};
&cpu0 {
@@ -284,6 +299,11 @@ &i2c5 {
status = "okay";
};
+&i2s {
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
&io_domains {
status = "okay";
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Fri, 1 Jan 2021 12:11:12 +0200
Subject: [PATCH] arm64: dts: rockchip: fix RK3399 vdec register witdh
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 418d16b0b648..4d5004c9c778 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -1276,7 +1276,7 @@ vpu_mmu: iommu@ff650800 {
vdec: video-codec@ff660000 {
compatible = "rockchip,rk3399-vdec";
- reg = <0x0 0xff660000 0x0 0x400>;
+ reg = <0x0 0xff660000 0x0 0x480>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "vdpu";
clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Wed, 10 Feb 2021 18:44:56 +0200
Subject: [PATCH] HACK: drm/gem: suppress warning about missing vm_flags
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/gpu/drm/drm_gem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 69c2c079d803..65fbffc4cbc7 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1093,7 +1093,7 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
drm_gem_object_put(obj);
return ret;
}
- WARN_ON(!(vma->vm_flags & VM_DONTEXPAND));
+ //WARN_ON(!(vma->vm_flags & VM_DONTEXPAND));
} else {
if (obj->funcs && obj->funcs->vm_ops)
vma->vm_ops = obj->funcs->vm_ops;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 25 Mar 2018 22:17:06 +0200
Subject: [PATCH] ASoC: hdmi-codec: fix channel allocation
---
sound/soc/codecs/hdmi-codec.c | 113 ++++++++++++++++------------------
1 file changed, 52 insertions(+), 61 deletions(-)
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 403d4c6a49a8..7505c3eee4c1 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -195,78 +195,69 @@ static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
*/
static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
{ .ca_id = 0x00, .n_ch = 2,
- .mask = FL | FR},
- /* 2.1 */
- { .ca_id = 0x01, .n_ch = 4,
- .mask = FL | FR | LFE},
- /* Dolby Surround */
+ .mask = FL | FR },
+ { .ca_id = 0x03, .n_ch = 4,
+ .mask = FL | FR | LFE | FC },
{ .ca_id = 0x02, .n_ch = 4,
.mask = FL | FR | FC },
- /* surround51 */
+ { .ca_id = 0x01, .n_ch = 4,
+ .mask = FL | FR | LFE },
{ .ca_id = 0x0b, .n_ch = 6,
- .mask = FL | FR | LFE | FC | RL | RR},
- /* surround40 */
- { .ca_id = 0x08, .n_ch = 6,
- .mask = FL | FR | RL | RR },
- /* surround41 */
- { .ca_id = 0x09, .n_ch = 6,
- .mask = FL | FR | LFE | RL | RR },
- /* surround50 */
+ .mask = FL | FR | LFE | FC | RL | RR },
{ .ca_id = 0x0a, .n_ch = 6,
.mask = FL | FR | FC | RL | RR },
- /* 6.1 */
- { .ca_id = 0x0f, .n_ch = 8,
- .mask = FL | FR | LFE | FC | RL | RR | RC },
- /* surround71 */
+ { .ca_id = 0x09, .n_ch = 6,
+ .mask = FL | FR | LFE | RL | RR },
+ { .ca_id = 0x08, .n_ch = 6,
+ .mask = FL | FR | RL | RR },
+ { .ca_id = 0x07, .n_ch = 6,
+ .mask = FL | FR | LFE | FC | RC },
+ { .ca_id = 0x06, .n_ch = 6,
+ .mask = FL | FR | FC | RC },
+ { .ca_id = 0x05, .n_ch = 6,
+ .mask = FL | FR | LFE | RC },
+ { .ca_id = 0x04, .n_ch = 6,
+ .mask = FL | FR | RC },
{ .ca_id = 0x13, .n_ch = 8,
.mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },
- /* others */
- { .ca_id = 0x03, .n_ch = 8,
- .mask = FL | FR | LFE | FC },
- { .ca_id = 0x04, .n_ch = 8,
- .mask = FL | FR | RC},
- { .ca_id = 0x05, .n_ch = 8,
- .mask = FL | FR | LFE | RC },
- { .ca_id = 0x06, .n_ch = 8,
- .mask = FL | FR | FC | RC },
- { .ca_id = 0x07, .n_ch = 8,
- .mask = FL | FR | LFE | FC | RC },
- { .ca_id = 0x0c, .n_ch = 8,
- .mask = FL | FR | RC | RL | RR },
- { .ca_id = 0x0d, .n_ch = 8,
- .mask = FL | FR | LFE | RL | RR | RC },
- { .ca_id = 0x0e, .n_ch = 8,
- .mask = FL | FR | FC | RL | RR | RC },
- { .ca_id = 0x10, .n_ch = 8,
- .mask = FL | FR | RL | RR | RLC | RRC },
- { .ca_id = 0x11, .n_ch = 8,
- .mask = FL | FR | LFE | RL | RR | RLC | RRC },
+ { .ca_id = 0x1f, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
{ .ca_id = 0x12, .n_ch = 8,
.mask = FL | FR | FC | RL | RR | RLC | RRC },
- { .ca_id = 0x14, .n_ch = 8,
- .mask = FL | FR | FLC | FRC },
- { .ca_id = 0x15, .n_ch = 8,
- .mask = FL | FR | LFE | FLC | FRC },
- { .ca_id = 0x16, .n_ch = 8,
- .mask = FL | FR | FC | FLC | FRC },
- { .ca_id = 0x17, .n_ch = 8,
- .mask = FL | FR | LFE | FC | FLC | FRC },
- { .ca_id = 0x18, .n_ch = 8,
- .mask = FL | FR | RC | FLC | FRC },
- { .ca_id = 0x19, .n_ch = 8,
- .mask = FL | FR | LFE | RC | FLC | FRC },
- { .ca_id = 0x1a, .n_ch = 8,
- .mask = FL | FR | RC | FC | FLC | FRC },
- { .ca_id = 0x1b, .n_ch = 8,
- .mask = FL | FR | LFE | RC | FC | FLC | FRC },
- { .ca_id = 0x1c, .n_ch = 8,
- .mask = FL | FR | RL | RR | FLC | FRC },
- { .ca_id = 0x1d, .n_ch = 8,
- .mask = FL | FR | LFE | RL | RR | FLC | FRC },
{ .ca_id = 0x1e, .n_ch = 8,
.mask = FL | FR | FC | RL | RR | FLC | FRC },
- { .ca_id = 0x1f, .n_ch = 8,
- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
+ { .ca_id = 0x11, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR | RLC | RRC },
+ { .ca_id = 0x1d, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR | FLC | FRC },
+ { .ca_id = 0x10, .n_ch = 8,
+ .mask = FL | FR | RL | RR | RLC | RRC },
+ { .ca_id = 0x1c, .n_ch = 8,
+ .mask = FL | FR | RL | RR | FLC | FRC },
+ { .ca_id = 0x0f, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | RL | RR | RC },
+ { .ca_id = 0x1b, .n_ch = 8,
+ .mask = FL | FR | LFE | RC | FC | FLC | FRC },
+ { .ca_id = 0x0e, .n_ch = 8,
+ .mask = FL | FR | FC | RL | RR | RC },
+ { .ca_id = 0x1a, .n_ch = 8,
+ .mask = FL | FR | RC | FC | FLC | FRC },
+ { .ca_id = 0x0d, .n_ch = 8,
+ .mask = FL | FR | LFE | RL | RR | RC },
+ { .ca_id = 0x19, .n_ch = 8,
+ .mask = FL | FR | LFE | RC | FLC | FRC },
+ { .ca_id = 0x0c, .n_ch = 8,
+ .mask = FL | FR | RC | RL | RR },
+ { .ca_id = 0x18, .n_ch = 8,
+ .mask = FL | FR | RC | FLC | FRC },
+ { .ca_id = 0x17, .n_ch = 8,
+ .mask = FL | FR | LFE | FC | FLC | FRC },
+ { .ca_id = 0x16, .n_ch = 8,
+ .mask = FL | FR | FC | FLC | FRC },
+ { .ca_id = 0x15, .n_ch = 8,
+ .mask = FL | FR | LFE | FLC | FRC },
+ { .ca_id = 0x14, .n_ch = 8,
+ .mask = FL | FR | FLC | FRC },
};
struct hdmi_codec_priv {

View File

@ -3085,3 +3085,368 @@ index 315894fc511b..3108d06ef7e0 100644
},
{
.mandatory = true,
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 30 Jan 2021 18:16:39 +0100
Subject: [PATCH] media: rkvdec: add variants support
rkvdec IP has different versions which among others differ in
the supported decoding formats.
This adds an variant implementation in order support other
than the currently supported RK3399 version.
Note: Since matching of supported codecs is index-based the
available codec options have been reordered here: from
supported by all versions to not commonly supported. This seems
the better soultion than duplicatiing code for every newly added IP.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/staging/media/rkvdec/rkvdec.c | 104 ++++++++++++++++++--------
drivers/staging/media/rkvdec/rkvdec.h | 10 +++
2 files changed, 84 insertions(+), 30 deletions(-)
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index 3108d06ef7e0..18ae1b15d0a4 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -270,21 +271,6 @@ static const u32 rkvdec_vp9_decoded_fmts[] = {
};
static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
- {
- .fourcc = V4L2_PIX_FMT_H264_SLICE,
- .frmsize = {
- .min_width = 48,
- .max_width = 4096,
- .step_width = 16,
- .min_height = 48,
- .max_height = 2304,
- .step_height = 16,
- },
- .ctrls = &rkvdec_h264_ctrls,
- .ops = &rkvdec_h264_fmt_ops,
- .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts),
- .decoded_fmts = rkvdec_h264_decoded_fmts,
- },
{
.fourcc = V4L2_PIX_FMT_HEVC_SLICE,
.frmsize = {
@@ -299,6 +285,23 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
.ops = &rkvdec_hevc_fmt_ops,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_hevc_decoded_fmts),
.decoded_fmts = rkvdec_hevc_decoded_fmts,
+ .capability = RKVDEC_CAPABILITY_HEVC,
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_H264_SLICE,
+ .frmsize = {
+ .min_width = 48,
+ .max_width = 4096,
+ .step_width = 16,
+ .min_height = 48,
+ .max_height = 2304,
+ .step_height = 16,
+ },
+ .ctrls = &rkvdec_h264_ctrls,
+ .ops = &rkvdec_h264_fmt_ops,
+ .num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts),
+ .decoded_fmts = rkvdec_h264_decoded_fmts,
+ .capability = RKVDEC_CAPABILITY_H264,
},
{
.fourcc = V4L2_PIX_FMT_VP9_FRAME,
@@ -314,16 +317,31 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
.ops = &rkvdec_vp9_fmt_ops,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts),
.decoded_fmts = rkvdec_vp9_decoded_fmts,
- }
+ .capability = RKVDEC_CAPABILITY_VP9,
+ },
};
static const struct rkvdec_coded_fmt_desc *
-rkvdec_find_coded_fmt_desc(u32 fourcc)
+rkvdec_default_coded_fmt_desc(unsigned int capabilities)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) {
- if (rkvdec_coded_fmts[i].fourcc == fourcc)
+ if (rkvdec_coded_fmts[i].capability & capabilities)
+ return &rkvdec_coded_fmts[i];
+ }
+
+ return NULL;
+}
+
+static const struct rkvdec_coded_fmt_desc *
+rkvdec_find_coded_fmt_desc(u32 fourcc, unsigned int capabilities)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) {
+ if (rkvdec_coded_fmts[i].fourcc == fourcc &&
+ (rkvdec_coded_fmts[i].capability & capabilities))
return &rkvdec_coded_fmts[i];
}
@@ -346,7 +364,7 @@ static void rkvdec_reset_coded_fmt(struct rkvdec_ctx *ctx)
{
struct v4l2_format *f = &ctx->coded_fmt;
- ctx->coded_fmt_desc = &rkvdec_coded_fmts[0];
+ ctx->coded_fmt_desc = rkvdec_default_coded_fmt_desc(ctx->dev->capabilities);
rkvdec_reset_fmt(ctx, f, ctx->coded_fmt_desc->fourcc);
f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
@@ -373,11 +391,13 @@ static int rkvdec_enum_framesizes(struct file *file, void *priv,
struct v4l2_frmsizeenum *fsize)
{
const struct rkvdec_coded_fmt_desc *fmt;
+ struct rkvdec_dev *rkvdec = video_drvdata(file);
if (fsize->index != 0)
return -EINVAL;
- fmt = rkvdec_find_coded_fmt_desc(fsize->pixel_format);
+ fmt = rkvdec_find_coded_fmt_desc(fsize->pixel_format,
+ rkvdec->capabilities);
if (!fmt)
return -EINVAL;
@@ -448,10 +468,11 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv,
struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv);
const struct rkvdec_coded_fmt_desc *desc;
- desc = rkvdec_find_coded_fmt_desc(pix_mp->pixelformat);
+ desc = rkvdec_find_coded_fmt_desc(pix_mp->pixelformat,
+ ctx->dev->capabilities);
if (!desc) {
- pix_mp->pixelformat = rkvdec_coded_fmts[0].fourcc;
- desc = &rkvdec_coded_fmts[0];
+ desc = rkvdec_default_coded_fmt_desc(ctx->dev->capabilities);
+ pix_mp->pixelformat = desc->fourcc;
}
v4l2_apply_frmsize_constraints(&pix_mp->width,
@@ -538,7 +559,8 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv,
if (ret)
return ret;
- desc = rkvdec_find_coded_fmt_desc(f->fmt.pix_mp.pixelformat);
+ desc = rkvdec_find_coded_fmt_desc(f->fmt.pix_mp.pixelformat,
+ ctx->dev->capabilities);
if (!desc)
return -EINVAL;
ctx->coded_fmt_desc = desc;
@@ -586,7 +608,10 @@ static int rkvdec_g_capture_fmt(struct file *file, void *priv,
static int rkvdec_enum_output_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- if (f->index >= ARRAY_SIZE(rkvdec_coded_fmts))
+ struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv);
+
+ if (f->index >= ARRAY_SIZE(rkvdec_coded_fmts) ||
+ !(ctx->dev->capabilities & rkvdec_coded_fmts[f->index].capability))
return -EINVAL;
f->pixelformat = rkvdec_coded_fmts[f->index].fourcc;
@@ -1012,14 +1037,17 @@ static int rkvdec_init_ctrls(struct rkvdec_ctx *ctx)
int ret;
for (i = 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++)
- nctrls += rkvdec_coded_fmts[i].ctrls->num_ctrls;
+ if (rkvdec_coded_fmts[i].capability & ctx->dev->capabilities)
+ nctrls += rkvdec_coded_fmts[i].ctrls->num_ctrls;
v4l2_ctrl_handler_init(&ctx->ctrl_hdl, nctrls);
for (i = 0; i < ARRAY_SIZE(rkvdec_coded_fmts); i++) {
- ret = rkvdec_add_ctrls(ctx, rkvdec_coded_fmts[i].ctrls);
- if (ret)
- goto err_free_handler;
+ if (rkvdec_coded_fmts[i].capability & ctx->dev->capabilities) {
+ ret = rkvdec_add_ctrls(ctx, rkvdec_coded_fmts[i].ctrls);
+ if (ret)
+ goto err_free_handler;
+ }
}
ret = v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
@@ -1217,8 +1245,17 @@ static void rkvdec_watchdog_func(struct work_struct *work)
}
}
+static const struct rkvdec_variant rk3399_rkvdec_variant = {
+ .capabilities = RKVDEC_CAPABILITY_H264 |
+ RKVDEC_CAPABILITY_HEVC |
+ RKVDEC_CAPABILITY_VP9
+};
+
static const struct of_device_id of_rkvdec_match[] = {
- { .compatible = "rockchip,rk3399-vdec" },
+ {
+ .compatible = "rockchip,rk3399-vdec",
+ .data = &rk3399_rkvdec_variant,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_rkvdec_match);
@@ -1231,6 +1268,7 @@ static int rkvdec_probe(struct platform_device *pdev)
{
struct rkvdec_dev *rkvdec;
struct resource *res;
+ const struct rkvdec_variant *variant;
unsigned int i;
int ret, irq;
@@ -1256,6 +1294,12 @@ static int rkvdec_probe(struct platform_device *pdev)
if (ret)
return ret;
+ variant = of_device_get_match_data(rkvdec->dev);
+ if (!variant)
+ return -EINVAL;
+
+ rkvdec->capabilities = variant->capabilities;
+
/*
* Bump ACLK to max. possible freq. (500 MHz) to improve performance
* When 4k video playback.
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
index a801668f5f7b..ff1cfd89a1e0 100644
--- a/drivers/staging/media/rkvdec/rkvdec.h
+++ b/drivers/staging/media/rkvdec/rkvdec.h
@@ -22,6 +22,10 @@
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-contig.h>
+#define RKVDEC_CAPABILITY_H264 BIT(0)
+#define RKVDEC_CAPABILITY_HEVC BIT(1)
+#define RKVDEC_CAPABILITY_VP9 BIT(2)
+
struct rkvdec_ctx;
struct rkvdec_ctrl_desc {
@@ -64,6 +68,10 @@ vb2_to_rkvdec_decoded_buf(struct vb2_buffer *buf)
base.vb.vb2_buf);
}
+struct rkvdec_variant {
+ unsigned int capabilities;
+};
+
struct rkvdec_coded_fmt_ops {
int (*adjust_fmt)(struct rkvdec_ctx *ctx,
struct v4l2_format *f);
@@ -83,6 +91,7 @@ struct rkvdec_coded_fmt_desc {
const struct rkvdec_coded_fmt_ops *ops;
unsigned int num_decoded_fmts;
const u32 *decoded_fmts;
+ unsigned int capability;
};
struct rkvdec_dev {
@@ -96,6 +105,7 @@ struct rkvdec_dev {
struct mutex vdev_lock; /* serializes ioctls */
struct delayed_work watchdog_work;
bool soft_reset;
+ unsigned int capabilities;
};
struct rkvdec_ctx {
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 30 Jan 2021 18:21:59 +0100
Subject: [PATCH] media: rkvdec: add RK3288 variant
This adds RK3288 variant to rkvdec driver. In this earlier version
of the IP only HEVC decoding is supported.
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
drivers/staging/media/rkvdec/rkvdec.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index 18ae1b15d0a4..c3b74ac8d979 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -1251,11 +1251,19 @@ static const struct rkvdec_variant rk3399_rkvdec_variant = {
RKVDEC_CAPABILITY_VP9
};
+static const struct rkvdec_variant rk3288_hevc_variant = {
+ .capabilities = RKVDEC_CAPABILITY_HEVC
+};
+
static const struct of_device_id of_rkvdec_match[] = {
{
.compatible = "rockchip,rk3399-vdec",
.data = &rk3399_rkvdec_variant,
},
+ {
+ .compatible = "rockchip,rk3288-hevc",
+ .data = &rk3288_hevc_variant,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_rkvdec_match);
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Bee <knaerzche@gmail.com>
Date: Sat, 30 Jan 2021 18:27:30 +0100
Subject: [PATCH] ARM: dts: RK3288: add hevc node
Signed-off-by: Alex Bee <knaerzche@gmail.com>
---
arch/arm/boot/dts/rk3288.dtsi | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 746acfac1e92..ba43ee6b91e8 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1271,6 +1271,23 @@ vpu_mmu: iommu@ff9a0800 {
power-domains = <&power RK3288_PD_VIDEO>;
};
+ hevc: hevc@ff9c0000 {
+ compatible = "rockchip,rk3288-hevc";
+ reg = <0x0 0xff9c0000 0x0 0x400>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "irq_dec";
+ clocks = <&cru ACLK_HEVC>, <&cru HCLK_HEVC>, <&cru SCLK_HEVC_CABAC>,
+ <&cru SCLK_HEVC_CORE>;
+ clock-names = "axi", "ahb", "cabac", "core";
+ assigned-clocks = <&cru ACLK_HEVC>, <&cru HCLK_HEVC>,
+ <&cru SCLK_HEVC_CORE>,
+ <&cru SCLK_HEVC_CABAC>;
+ assigned-clock-rates = <400000000>, <100000000>,
+ <300000000>, <300000000>;
+ iommus = <&hevc_mmu>;
+ power-domains = <&power RK3288_PD_HEVC>;
+ };
+
hevc_mmu: iommu@ff9c0440 {
compatible = "rockchip,iommu";
reg = <0x0 0xff9c0440 0x0 0x40>, <0x0 0xff9c0480 0x0 0x40>;
@@ -1279,7 +1296,7 @@ hevc_mmu: iommu@ff9c0440 {
clocks = <&cru ACLK_HEVC>, <&cru HCLK_HEVC>;
clock-names = "aclk", "iface";
#iommu-cells = <0>;
- status = "disabled";
+ power-domains = <&power RK3288_PD_HEVC>;
};
gpu: gpu@ffa30000 {

File diff suppressed because it is too large Load Diff