mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 05:36:47 +00:00
Merge pull request #5143 from knaerzche/rk-update-2
Rockchip: next update
This commit is contained in:
commit
058b49e3e1
@ -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>
|
From: Jonas Karlman <jonas@kwiboo.se>
|
||||||
Date: Sun, 5 Aug 2018 20:58:54 +0200
|
Date: Sun, 5 Aug 2018 20:58:54 +0200
|
||||||
Subject: [PATCH] rockchip: rk3288: get serial and ethaddr from efuse
|
Subject: [PATCH] rockchip: rk3288: get serial and ethaddr from efuse
|
||||||
|
|
||||||
---
|
---
|
||||||
arch/arm/dts/rk3288.dtsi | 5 ++---
|
arch/arm/dts/rk3288.dtsi | 5 ++---
|
||||||
configs/miqi-rk3288_defconfig | 2 ++
|
configs/miqi-rk3288_defconfig | 3 +++
|
||||||
configs/tinker-rk3288_defconfig | 1 +
|
configs/tinker-rk3288_defconfig | 2 ++
|
||||||
3 files changed, 5 insertions(+), 3 deletions(-)
|
3 files changed, 7 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
|
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
|
||||||
index 20adb0dece..8b085ee6dc 100644
|
index 20adb0dece..8b085ee6dc 100644
|
||||||
@ -26,27 +26,29 @@ index 20adb0dece..8b085ee6dc 100644
|
|||||||
|
|
||||||
gic: interrupt-controller@ffc01000 {
|
gic: interrupt-controller@ffc01000 {
|
||||||
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
|
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
|
--- a/configs/miqi-rk3288_defconfig
|
||||||
+++ b/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_SYS_I2C_ROCKCHIP=y
|
||||||
CONFIG_DM_KEY=y
|
CONFIG_DM_KEY=y
|
||||||
CONFIG_ADC_KEY=y
|
CONFIG_ADC_KEY=y
|
||||||
+CONFIG_MISC=y
|
+CONFIG_MISC=y
|
||||||
+CONFIG_ROCKCHIP_EFUSE=y
|
+CONFIG_ROCKCHIP_EFUSE=y
|
||||||
|
+CONFIG_SHA256=y
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
CONFIG_DM_ETH=y
|
CONFIG_DM_ETH=y
|
||||||
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
|
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
|
--- a/configs/tinker-rk3288_defconfig
|
||||||
+++ b/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_ROCKCHIP_GPIO=y
|
||||||
CONFIG_SYS_I2C_ROCKCHIP=y
|
CONFIG_SYS_I2C_ROCKCHIP=y
|
||||||
CONFIG_MISC=y
|
CONFIG_MISC=y
|
||||||
+CONFIG_ROCKCHIP_EFUSE=y
|
+CONFIG_ROCKCHIP_EFUSE=y
|
||||||
|
+CONFIG_SHA256=y
|
||||||
CONFIG_I2C_EEPROM=y
|
CONFIG_I2C_EEPROM=y
|
||||||
CONFIG_MMC_DW=y
|
CONFIG_MMC_DW=y
|
||||||
CONFIG_MMC_DW_ROCKCHIP=y
|
CONFIG_MMC_DW_ROCKCHIP=y
|
||||||
|
@ -2929,6 +2929,7 @@ CONFIG_SMS_SIANO_RC=y
|
|||||||
# CONFIG_V4L_PLATFORM_DRIVERS is not set
|
# CONFIG_V4L_PLATFORM_DRIVERS is not set
|
||||||
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
||||||
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
|
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
|
||||||
|
CONFIG_VIDEO_ROCKCHIP_IEP=m
|
||||||
CONFIG_VIDEO_ROCKCHIP_RGA=m
|
CONFIG_VIDEO_ROCKCHIP_RGA=m
|
||||||
# CONFIG_DVB_PLATFORM_DRIVERS is not set
|
# CONFIG_DVB_PLATFORM_DRIVERS is not set
|
||||||
|
|
||||||
|
@ -3019,6 +3019,7 @@ CONFIG_SMS_SIANO_RC=y
|
|||||||
# CONFIG_V4L_PLATFORM_DRIVERS is not set
|
# CONFIG_V4L_PLATFORM_DRIVERS is not set
|
||||||
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
||||||
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
|
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
|
||||||
|
CONFIG_VIDEO_ROCKCHIP_IEP=m
|
||||||
CONFIG_VIDEO_ROCKCHIP_RGA=m
|
CONFIG_VIDEO_ROCKCHIP_RGA=m
|
||||||
# CONFIG_DVB_PLATFORM_DRIVERS is not set
|
# CONFIG_DVB_PLATFORM_DRIVERS is not set
|
||||||
|
|
||||||
|
@ -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/
|
@ -2091,7 +2091,8 @@ CONFIG_AR5523=m
|
|||||||
# CONFIG_WIL6210 is not set
|
# CONFIG_WIL6210 is not set
|
||||||
CONFIG_ATH10K=m
|
CONFIG_ATH10K=m
|
||||||
CONFIG_ATH10K_CE=y
|
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_SDIO is not set
|
||||||
CONFIG_ATH10K_USB=m
|
CONFIG_ATH10K_USB=m
|
||||||
# CONFIG_ATH10K_DEBUG is not set
|
# CONFIG_ATH10K_DEBUG is not set
|
||||||
@ -2125,18 +2126,39 @@ CONFIG_BRCMUTIL=m
|
|||||||
# CONFIG_BRCMSMAC is not set
|
# CONFIG_BRCMSMAC is not set
|
||||||
CONFIG_BRCMFMAC=m
|
CONFIG_BRCMFMAC=m
|
||||||
CONFIG_BRCMFMAC_PROTO_BCDC=y
|
CONFIG_BRCMFMAC_PROTO_BCDC=y
|
||||||
|
CONFIG_BRCMFMAC_PROTO_MSGBUF=y
|
||||||
CONFIG_BRCMFMAC_SDIO=y
|
CONFIG_BRCMFMAC_SDIO=y
|
||||||
CONFIG_BRCMFMAC_USB=y
|
CONFIG_BRCMFMAC_USB=y
|
||||||
# CONFIG_BRCMFMAC_PCIE is not set
|
CONFIG_BRCMFMAC_PCIE=y
|
||||||
# CONFIG_BRCM_TRACING is not set
|
# CONFIG_BRCM_TRACING is not set
|
||||||
# CONFIG_BRCMDBG is not set
|
# CONFIG_BRCMDBG is not set
|
||||||
CONFIG_WLAN_VENDOR_CISCO=y
|
CONFIG_WLAN_VENDOR_CISCO=y
|
||||||
CONFIG_WLAN_VENDOR_INTEL=y
|
CONFIG_WLAN_VENDOR_INTEL=y
|
||||||
# CONFIG_IPW2100 is not set
|
# CONFIG_IPW2100 is not set
|
||||||
# CONFIG_IPW2200 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_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_WLAN_VENDOR_INTERSIL=y
|
||||||
# CONFIG_HOSTAP is not set
|
# CONFIG_HOSTAP is not set
|
||||||
# CONFIG_HERMES is not set
|
# CONFIG_HERMES is not set
|
||||||
@ -2158,7 +2180,7 @@ CONFIG_LIBERTAS_THINFIRM=m
|
|||||||
CONFIG_LIBERTAS_THINFIRM_USB=m
|
CONFIG_LIBERTAS_THINFIRM_USB=m
|
||||||
CONFIG_MWIFIEX=m
|
CONFIG_MWIFIEX=m
|
||||||
# CONFIG_MWIFIEX_SDIO is not set
|
# CONFIG_MWIFIEX_SDIO is not set
|
||||||
# CONFIG_MWIFIEX_PCIE is not set
|
CONFIG_MWIFIEX_PCIE=m
|
||||||
CONFIG_MWIFIEX_USB=m
|
CONFIG_MWIFIEX_USB=m
|
||||||
# CONFIG_MWL8K is not set
|
# CONFIG_MWL8K is not set
|
||||||
CONFIG_WLAN_VENDOR_MEDIATEK=y
|
CONFIG_WLAN_VENDOR_MEDIATEK=y
|
||||||
@ -2171,17 +2193,17 @@ CONFIG_MT76x02_LIB=m
|
|||||||
CONFIG_MT76x02_USB=m
|
CONFIG_MT76x02_USB=m
|
||||||
CONFIG_MT76x0_COMMON=m
|
CONFIG_MT76x0_COMMON=m
|
||||||
CONFIG_MT76x0U=m
|
CONFIG_MT76x0U=m
|
||||||
# CONFIG_MT76x0E is not set
|
CONFIG_MT76x0E=m
|
||||||
CONFIG_MT76x2_COMMON=m
|
CONFIG_MT76x2_COMMON=m
|
||||||
# CONFIG_MT76x2E is not set
|
CONFIG_MT76x2E=m
|
||||||
CONFIG_MT76x2U=m
|
CONFIG_MT76x2U=m
|
||||||
# CONFIG_MT7603E is not set
|
CONFIG_MT7603E=m
|
||||||
CONFIG_MT7615_COMMON=m
|
CONFIG_MT7615_COMMON=m
|
||||||
# CONFIG_MT7615E is not set
|
CONFIG_MT7615E=m
|
||||||
CONFIG_MT7663_USB_SDIO_COMMON=m
|
CONFIG_MT7663_USB_SDIO_COMMON=m
|
||||||
CONFIG_MT7663U=m
|
CONFIG_MT7663U=m
|
||||||
CONFIG_MT7663S=m
|
CONFIG_MT7663S=m
|
||||||
# CONFIG_MT7915E is not set
|
CONFIG_MT7915E=m
|
||||||
CONFIG_WLAN_VENDOR_MICROCHIP=y
|
CONFIG_WLAN_VENDOR_MICROCHIP=y
|
||||||
# CONFIG_WILC1000_SDIO is not set
|
# CONFIG_WILC1000_SDIO is not set
|
||||||
# CONFIG_WILC1000_SPI 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_PLATFORM_DRIVERS is not set
|
||||||
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
CONFIG_V4L_MEM2MEM_DRIVERS=y
|
||||||
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
|
# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
|
||||||
|
CONFIG_VIDEO_ROCKCHIP_IEP=m
|
||||||
CONFIG_VIDEO_ROCKCHIP_RGA=m
|
CONFIG_VIDEO_ROCKCHIP_RGA=m
|
||||||
# CONFIG_DVB_PLATFORM_DRIVERS is not set
|
# CONFIG_DVB_PLATFORM_DRIVERS is not set
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
};
|
@ -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;
|
@ -232,3 +232,456 @@ index 80053d91a301..2c55e1852c3d 100644
|
|||||||
.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
|
.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
|
||||||
.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
|
.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
|
||||||
.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
|
.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;
|
||||||
|
@ -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";
|
|
||||||
};
|
|
@ -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 {
|
@ -3085,3 +3085,368 @@ index 315894fc511b..3108d06ef7e0 100644
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.mandatory = true,
|
.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
Loading…
x
Reference in New Issue
Block a user