mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Update OpenWrt
This commit is contained in:
parent
0dd5bbf0fa
commit
da818da21b
43 changed files with 1 additions and 5163 deletions
2
build.sh
2
build.sh
|
@ -56,7 +56,7 @@ else
|
|||
fi
|
||||
|
||||
#_get_repo source https://github.com/ysurac/openmptcprouter-source "master"
|
||||
_get_repo "$OMR_TARGET/source" https://github.com/openwrt/openwrt "ccf3bac6f3f90f9281d6ec2569265b24e13435fa"
|
||||
_get_repo "$OMR_TARGET/source" https://github.com/openwrt/openwrt "7d542dc8047d276517b296132926e722004065e0"
|
||||
_get_repo feeds/packages https://github.com/openwrt/packages "5646b4ce74f151f8c36d94a7577f60f0c359d09d"
|
||||
_get_repo feeds/luci https://github.com/openwrt/luci "3fffcdef61b19c8fc6a4fb448cf5abb88d4ba002"
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
From 5d1250c4a623fba8f10e3578f10cbde75c0f41ff Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Wed, 31 Jul 2019 17:36:34 +0100
|
||||
Subject: [PATCH 734/826] drm/vc4: A present but empty dmas disables audio
|
||||
|
||||
Overlays are unable to remove properties in the base DTB, but they
|
||||
can overwrite them. Allow a present but empty 'dmas' property
|
||||
to also disable the HDMI audio interface.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/2489
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||
index 2f276222e30f..be80769d7b5b 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||
@@ -1087,10 +1087,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
|
||||
struct device *dev = &hdmi->pdev->dev;
|
||||
const __be32 *addr;
|
||||
int ret;
|
||||
+ int len;
|
||||
|
||||
- if (!of_find_property(dev->of_node, "dmas", NULL)) {
|
||||
+ if (!of_find_property(dev->of_node, "dmas", &len) ||
|
||||
+ len == 0) {
|
||||
dev_warn(dev,
|
||||
- "'dmas' DT property is missing, no HDMI audio\n");
|
||||
+ "'dmas' DT property is missing or empty, no HDMI audio\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
From e8e84b725b2d9048f34c57c85893e4c35d94ea9e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Wed, 31 Jul 2019 17:39:37 +0100
|
||||
Subject: [PATCH 735/826] overlays: Add audio parameter to vc4-kms-v3d
|
||||
|
||||
The audio parameter to the vc4-kms-v3d overlay allows audio support
|
||||
to be disabled (it defaults to on) by adding "audio=off" to the
|
||||
dtoverlay parameters.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/2489
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 1 +
|
||||
arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 8 ++++++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
|
||||
index 203041654d84..6131ac3d967c 100644
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -2480,6 +2480,7 @@ Params: cma-256 CMA is 256MB (needs 1GB)
|
||||
cma-128 CMA is 128MB
|
||||
cma-96 CMA is 96MB
|
||||
cma-64 CMA is 64MB
|
||||
+ audio Enable or disable audio over HDMI (default "on")
|
||||
|
||||
|
||||
Name: vga666
|
||||
diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
|
||||
index 19e1d2548e7b..c5f687e8bcb9 100644
|
||||
--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
|
||||
@@ -134,11 +134,19 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ fragment@17 {
|
||||
+ target = <&hdmi>;
|
||||
+ __dormant__ {
|
||||
+ dmas;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
cma-256 = <0>,"+0-1-2-3-4";
|
||||
cma-192 = <0>,"-0+1-2-3-4";
|
||||
cma-128 = <0>,"-0-1+2-3-4";
|
||||
cma-96 = <0>,"-0-1-2+3-4";
|
||||
cma-64 = <0>,"-0-1-2-3+4";
|
||||
+ audio = <0>,"!17";
|
||||
};
|
||||
};
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From 3560542c15a3b71ecd58e347f7fcfc3b6e7770a2 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Wed, 31 Jul 2019 17:41:47 +0100
|
||||
Subject: [PATCH 736/826] overlays: Update the upstream overlay
|
||||
|
||||
The recent vc4-kms-v3d commit has changed the content of the
|
||||
upstream overlay (even though the extra fragment is disabled).
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/upstream-overlay.dts | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/overlays/upstream-overlay.dts b/arch/arm/boot/dts/overlays/upstream-overlay.dts
|
||||
index 48e0ef61952c..6112640837fc 100644
|
||||
--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
|
||||
@@ -110,6 +110,12 @@
|
||||
};
|
||||
};
|
||||
fragment@17 {
|
||||
+ target = <&hdmi>;
|
||||
+ __dormant__ {
|
||||
+ dmas;
|
||||
+ };
|
||||
+ };
|
||||
+ fragment@18 {
|
||||
target = <&usb>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
From 9543c9ffe07dcfd7b7a93e9009bd004c3c1cfdec Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Thu, 1 Aug 2019 08:58:48 +0100
|
||||
Subject: [PATCH 737/826] can: mcp251x: Allow more time after a reset
|
||||
|
||||
Some boards take longer than 5ms to power up after a reset, so allow
|
||||
a few retry attempts before giving up.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/2767
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
drivers/net/can/spi/mcp251x.c | 15 ++++++++++++---
|
||||
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
|
||||
index cae0f5b633d0..c5c2ac423fc9 100644
|
||||
--- a/drivers/net/can/spi/mcp251x.c
|
||||
+++ b/drivers/net/can/spi/mcp251x.c
|
||||
@@ -628,6 +628,7 @@ static int mcp251x_hw_reset(struct spi_device *spi)
|
||||
struct mcp251x_priv *priv = spi_get_drvdata(spi);
|
||||
u8 reg;
|
||||
int ret;
|
||||
+ int retries = 10;
|
||||
|
||||
/* Wait for oscillator startup timer after power up */
|
||||
mdelay(MCP251X_OST_DELAY_MS);
|
||||
@@ -637,10 +638,18 @@ static int mcp251x_hw_reset(struct spi_device *spi)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- /* Wait for oscillator startup timer after reset */
|
||||
- mdelay(MCP251X_OST_DELAY_MS);
|
||||
+ /*
|
||||
+ * Wait for oscillator startup timer after reset
|
||||
+ *
|
||||
+ * Some devices can take longer than the expected 5ms to wake
|
||||
+ * up, so allow a few retries.
|
||||
+ */
|
||||
+
|
||||
+ do {
|
||||
+ mdelay(MCP251X_OST_DELAY_MS);
|
||||
+ reg = mcp251x_read_reg(spi, CANSTAT);
|
||||
+ } while (!reg && retries--);
|
||||
|
||||
- reg = mcp251x_read_reg(spi, CANSTAT);
|
||||
if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
|
||||
return -ENODEV;
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
From e27970cd68f7b52523ce0992446f43b7ed2fb211 Mon Sep 17 00:00:00 2001
|
||||
From: James Hughes <james.hughes@raspberrypi.org>
|
||||
Date: Mon, 29 Jul 2019 12:02:59 +0100
|
||||
Subject: [PATCH 738/826] Fixup FKMS interrupt handing for non-existent display
|
||||
|
||||
If an errant interrupt flag was received from a non-existent display,
|
||||
a NULL pointer access was made. Protect against this by checking if a
|
||||
second display is present prior to checking the interrupt flags.
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 17 ++++++++++-------
|
||||
1 file changed, 10 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
index 8f3fe6f9246e..bcbd2f709c7f 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
@@ -1056,14 +1056,17 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
|
||||
vc4_crtc_handle_page_flip(crtc_list[0]);
|
||||
}
|
||||
|
||||
- /* Check for the secondary display too */
|
||||
- chan = readl(crtc_list[0]->regs + SMIDSW1);
|
||||
+ if (crtc_list[1]) {
|
||||
+ /* Check for the secondary display too */
|
||||
+ chan = readl(crtc_list[0]->regs + SMIDSW1);
|
||||
|
||||
- if (chan & 1) {
|
||||
- writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
|
||||
- if (crtc_list[1]->vblank_enabled)
|
||||
- drm_crtc_handle_vblank(&crtc_list[1]->base);
|
||||
- vc4_crtc_handle_page_flip(crtc_list[1]);
|
||||
+ if (chan & 1) {
|
||||
+ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
|
||||
+
|
||||
+ if (crtc_list[1]->vblank_enabled)
|
||||
+ drm_crtc_handle_vblank(&crtc_list[1]->base);
|
||||
+ vc4_crtc_handle_page_flip(crtc_list[1]);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
From f8838a2ac019050145abb3931dfb9270b8208e2d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Sun, 28 Jul 2019 22:22:36 +0100
|
||||
Subject: [PATCH 739/826] drivers: char: Use correct name for the Raspberry Pi
|
||||
video decoder
|
||||
|
||||
Replace the old code name with a more appropriate name - RPiVid.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm/boot/dts/bcm2838.dtsi | 10 +-
|
||||
arch/arm/configs/bcm2711_defconfig | 2 +-
|
||||
drivers/char/broadcom/Kconfig | 8 +-
|
||||
drivers/char/broadcom/Makefile | 2 +-
|
||||
.../broadcom/{argon-mem.c => rpivid-mem.c} | 105 +++++++++---------
|
||||
drivers/mfd/bcm2835-pm.c | 12 +-
|
||||
drivers/soc/bcm/bcm2835-power.c | 6 +-
|
||||
include/linux/mfd/bcm2835-pm.h | 2 +-
|
||||
8 files changed, 71 insertions(+), 76 deletions(-)
|
||||
rename drivers/char/broadcom/{argon-mem.c => rpivid-mem.c} (69%)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/bcm2838.dtsi b/arch/arm/boot/dts/bcm2838.dtsi
|
||||
index 9d349b3fa652..1d321ad6640a 100644
|
||||
--- a/arch/arm/boot/dts/bcm2838.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm2838.dtsi
|
||||
@@ -409,26 +409,26 @@
|
||||
};
|
||||
|
||||
hevc-decoder@7eb00000 {
|
||||
- compatible = "raspberrypi,argon-hevc-decoder";
|
||||
+ compatible = "raspberrypi,rpivid-hevc-decoder";
|
||||
reg = <0x0 0x7eb00000 0x10000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
- argon-local-intc@7eb10000 {
|
||||
- compatible = "raspberrypi,argon-local-intc";
|
||||
+ rpivid-local-intc@7eb10000 {
|
||||
+ compatible = "raspberrypi,rpivid-local-intc";
|
||||
reg = <0x0 0x7eb10000 0x1000>;
|
||||
status = "okay";
|
||||
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
h264-decoder@7eb20000 {
|
||||
- compatible = "raspberrypi,argon-h264-decoder";
|
||||
+ compatible = "raspberrypi,rpivid-h264-decoder";
|
||||
reg = <0x0 0x7eb20000 0x10000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
vp9-decoder@7eb30000 {
|
||||
- compatible = "raspberrypi,argon-vp9-decoder";
|
||||
+ compatible = "raspberrypi,rpivid-vp9-decoder";
|
||||
reg = <0x0 0x7eb30000 0x10000>;
|
||||
status = "okay";
|
||||
};
|
||||
diff --git a/arch/arm/configs/bcm2711_defconfig b/arch/arm/configs/bcm2711_defconfig
|
||||
index 159169797d57..2ff5dd6f5175 100644
|
||||
--- a/arch/arm/configs/bcm2711_defconfig
|
||||
+++ b/arch/arm/configs/bcm2711_defconfig
|
||||
@@ -650,7 +650,7 @@ CONFIG_BRCM_CHAR_DRIVERS=y
|
||||
CONFIG_BCM_VCIO=y
|
||||
CONFIG_BCM_VC_SM=y
|
||||
CONFIG_BCM2835_DEVGPIOMEM=y
|
||||
-CONFIG_ARGON_MEM=m
|
||||
+CONFIG_RPIVID_MEM=m
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_SERIAL_8250=y
|
||||
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
|
||||
diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig
|
||||
index 4ba3fb4049eb..6f9b37bf6b8a 100644
|
||||
--- a/drivers/char/broadcom/Kconfig
|
||||
+++ b/drivers/char/broadcom/Kconfig
|
||||
@@ -50,10 +50,10 @@ config BCM2835_SMI_DEV
|
||||
Broadcom's Secondary Memory interface. The low-level functionality is provided
|
||||
by the SMI driver itself.
|
||||
|
||||
-config ARGON_MEM
|
||||
- tristate "Character device driver for the Argon decoder hardware"
|
||||
+config RPIVID_MEM
|
||||
+ tristate "Character device driver for the Raspberry Pi RPIVid video decoder hardware"
|
||||
default n
|
||||
help
|
||||
This driver provides a character device interface for memory-map operations
|
||||
- so userspace tools can access the control and status registers of the Argon
|
||||
- video decoder hardware.
|
||||
+ so userspace tools can access the control and status registers of the
|
||||
+ Raspberry Pi RPiVid video decoder hardware.
|
||||
diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile
|
||||
index 50767fc1b569..e06026539719 100644
|
||||
--- a/drivers/char/broadcom/Makefile
|
||||
+++ b/drivers/char/broadcom/Makefile
|
||||
@@ -4,4 +4,4 @@ obj-$(CONFIG_BCM_VC_SM) += vc_sm/
|
||||
|
||||
obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o
|
||||
obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o
|
||||
-obj-$(CONFIG_ARGON_MEM) += argon-mem.o
|
||||
+obj-$(CONFIG_RPIVID_MEM) += rpivid-mem.o
|
||||
diff --git a/drivers/char/broadcom/argon-mem.c b/drivers/char/broadcom/rpivid-mem.c
|
||||
similarity index 69%
|
||||
rename from drivers/char/broadcom/argon-mem.c
|
||||
rename to drivers/char/broadcom/rpivid-mem.c
|
||||
index 01c36db7754a..fae84c7d3cf4 100644
|
||||
--- a/drivers/char/broadcom/argon-mem.c
|
||||
+++ b/drivers/char/broadcom/rpivid-mem.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
- * argon-mem.c - character device access to the Argon decoder registers
|
||||
+ * rpivid-mem.c - character device access to the RPiVid decoder registers
|
||||
*
|
||||
* Based on bcm2835-gpiomem.c. Provides IO memory access to the decoder
|
||||
* register blocks such that ffmpeg plugins can access the hardware.
|
||||
@@ -48,36 +48,36 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
-#define DRIVER_NAME "argon-mem"
|
||||
+#define DRIVER_NAME "rpivid-mem"
|
||||
#define DEVICE_MINOR 0
|
||||
|
||||
-struct argon_mem_priv {
|
||||
+struct rpivid_mem_priv {
|
||||
dev_t devid;
|
||||
struct class *class;
|
||||
- struct cdev argon_mem_cdev;
|
||||
+ struct cdev rpivid_mem_cdev;
|
||||
unsigned long regs_phys;
|
||||
unsigned long mem_window_len;
|
||||
struct device *dev;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
-static int argon_mem_open(struct inode *inode, struct file *file)
|
||||
+static int rpivid_mem_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int dev = iminor(inode);
|
||||
int ret = 0;
|
||||
- struct argon_mem_priv *priv;
|
||||
+ struct rpivid_mem_priv *priv;
|
||||
if (dev != DEVICE_MINOR)
|
||||
ret = -ENXIO;
|
||||
|
||||
- priv = container_of(inode->i_cdev, struct argon_mem_priv,
|
||||
- argon_mem_cdev);
|
||||
+ priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
|
||||
+ rpivid_mem_cdev);
|
||||
if (!priv)
|
||||
return -EINVAL;
|
||||
file->private_data = priv;
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int argon_mem_release(struct inode *inode, struct file *file)
|
||||
+static int rpivid_mem_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int dev = iminor(inode);
|
||||
int ret = 0;
|
||||
@@ -88,15 +88,15 @@ static int argon_mem_release(struct inode *inode, struct file *file)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static const struct vm_operations_struct argon_mem_vm_ops = {
|
||||
+static const struct vm_operations_struct rpivid_mem_vm_ops = {
|
||||
#ifdef CONFIG_HAVE_IOREMAP_PROT
|
||||
.access = generic_access_phys
|
||||
#endif
|
||||
};
|
||||
|
||||
-static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
+static int rpivid_mem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
- struct argon_mem_priv *priv;
|
||||
+ struct rpivid_mem_priv *priv;
|
||||
unsigned long pages;
|
||||
|
||||
priv = file->private_data;
|
||||
@@ -108,7 +108,7 @@ static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
vma->vm_page_prot = phys_mem_access_prot(file, pages,
|
||||
priv->mem_window_len,
|
||||
vma->vm_page_prot);
|
||||
- vma->vm_ops = &argon_mem_vm_ops;
|
||||
+ vma->vm_ops = &rpivid_mem_vm_ops;
|
||||
if (remap_pfn_range(vma, vma->vm_start,
|
||||
pages,
|
||||
priv->mem_window_len,
|
||||
@@ -119,28 +119,28 @@ static int argon_mem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
}
|
||||
|
||||
static const struct file_operations
|
||||
-argon_mem_fops = {
|
||||
+rpivid_mem_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
- .open = argon_mem_open,
|
||||
- .release = argon_mem_release,
|
||||
- .mmap = argon_mem_mmap,
|
||||
+ .open = rpivid_mem_open,
|
||||
+ .release = rpivid_mem_release,
|
||||
+ .mmap = rpivid_mem_mmap,
|
||||
};
|
||||
|
||||
-static const struct of_device_id argon_mem_of_match[];
|
||||
-static int argon_mem_probe(struct platform_device *pdev)
|
||||
+static const struct of_device_id rpivid_mem_of_match[];
|
||||
+static int rpivid_mem_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
void *ptr_err;
|
||||
const struct of_device_id *id;
|
||||
struct device *dev = &pdev->dev;
|
||||
- struct device *argon_mem_dev;
|
||||
+ struct device *rpivid_mem_dev;
|
||||
struct resource *ioresource;
|
||||
- struct argon_mem_priv *priv;
|
||||
+ struct rpivid_mem_priv *priv;
|
||||
|
||||
|
||||
/* Allocate buffers and instance data */
|
||||
|
||||
- priv = kzalloc(sizeof(struct argon_mem_priv), GFP_KERNEL);
|
||||
+ priv = kzalloc(sizeof(struct rpivid_mem_priv), GFP_KERNEL);
|
||||
|
||||
if (!priv) {
|
||||
err = -ENOMEM;
|
||||
@@ -149,7 +149,7 @@ static int argon_mem_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->dev = dev;
|
||||
- id = of_match_device(argon_mem_of_match, dev);
|
||||
+ id = of_match_device(rpivid_mem_of_match, dev);
|
||||
if (!id)
|
||||
return -EINVAL;
|
||||
priv->name = id->data;
|
||||
@@ -172,9 +172,9 @@ static int argon_mem_probe(struct platform_device *pdev)
|
||||
dev_err(priv->dev, "unable to allocate device number");
|
||||
goto failed_alloc_chrdev;
|
||||
}
|
||||
- cdev_init(&priv->argon_mem_cdev, &argon_mem_fops);
|
||||
- priv->argon_mem_cdev.owner = THIS_MODULE;
|
||||
- err = cdev_add(&priv->argon_mem_cdev, priv->devid, 1);
|
||||
+ cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
|
||||
+ priv->rpivid_mem_cdev.owner = THIS_MODULE;
|
||||
+ err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
|
||||
if (err != 0) {
|
||||
dev_err(priv->dev, "unable to register device");
|
||||
goto failed_cdev_add;
|
||||
@@ -187,10 +187,10 @@ static int argon_mem_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(ptr_err))
|
||||
goto failed_class_create;
|
||||
|
||||
- argon_mem_dev = device_create(priv->class, NULL,
|
||||
+ rpivid_mem_dev = device_create(priv->class, NULL,
|
||||
priv->devid, NULL,
|
||||
priv->name);
|
||||
- ptr_err = argon_mem_dev;
|
||||
+ ptr_err = rpivid_mem_dev;
|
||||
if (IS_ERR(ptr_err))
|
||||
goto failed_device_create;
|
||||
|
||||
@@ -202,7 +202,7 @@ static int argon_mem_probe(struct platform_device *pdev)
|
||||
failed_device_create:
|
||||
class_destroy(priv->class);
|
||||
failed_class_create:
|
||||
- cdev_del(&priv->argon_mem_cdev);
|
||||
+ cdev_del(&priv->rpivid_mem_cdev);
|
||||
err = PTR_ERR(ptr_err);
|
||||
failed_cdev_add:
|
||||
unregister_chrdev_region(priv->devid, 1);
|
||||
@@ -210,18 +210,18 @@ static int argon_mem_probe(struct platform_device *pdev)
|
||||
failed_get_resource:
|
||||
kfree(priv);
|
||||
failed_inst_alloc:
|
||||
- dev_err(priv->dev, "could not load argon_mem");
|
||||
+ dev_err(priv->dev, "could not load rpivid_mem");
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int argon_mem_remove(struct platform_device *pdev)
|
||||
+static int rpivid_mem_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
- struct argon_mem_priv *priv = platform_get_drvdata(pdev);
|
||||
+ struct rpivid_mem_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
device_destroy(priv->class, priv->devid);
|
||||
class_destroy(priv->class);
|
||||
- cdev_del(&priv->argon_mem_cdev);
|
||||
+ cdev_del(&priv->rpivid_mem_cdev);
|
||||
unregister_chrdev_region(priv->devid, 1);
|
||||
kfree(priv);
|
||||
|
||||
@@ -229,49 +229,44 @@ static int argon_mem_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const char argon_hevc_name[] = "argon-hevcmem";
|
||||
-static const char argon_h264_name[] = "argon-h264mem";
|
||||
-static const char argon_vp9_name[] = "argon-vp9mem";
|
||||
-static const char argon_intc_name[] = "argon-intcmem";
|
||||
-
|
||||
-static const struct of_device_id argon_mem_of_match[] = {
|
||||
+static const struct of_device_id rpivid_mem_of_match[] = {
|
||||
{
|
||||
- .compatible = "raspberrypi,argon-hevc-decoder",
|
||||
- .data = &argon_hevc_name,
|
||||
+ .compatible = "raspberrypi,rpivid-hevc-decoder",
|
||||
+ .data = "rpivid-hevcmem",
|
||||
},
|
||||
{
|
||||
- .compatible = "raspberrypi,argon-h264-decoder",
|
||||
- .data = &argon_h264_name,
|
||||
+ .compatible = "raspberrypi,rpivid-h264-decoder",
|
||||
+ .data = "rpivid-h264mem",
|
||||
},
|
||||
{
|
||||
- .compatible = "raspberrypi,argon-vp9-decoder",
|
||||
- .data = &argon_vp9_name,
|
||||
+ .compatible = "raspberrypi,rpivid-vp9-decoder",
|
||||
+ .data = "rpivid-vp9mem",
|
||||
},
|
||||
/* The "intc" is included as this block of hardware contains the
|
||||
* "frame done" status flags.
|
||||
*/
|
||||
{
|
||||
- .compatible = "raspberrypi,argon-local-intc",
|
||||
- .data = &argon_intc_name,
|
||||
+ .compatible = "raspberrypi,rpivid-local-intc",
|
||||
+ .data = "rpivid-intcmem",
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
-MODULE_DEVICE_TABLE(of, argon_mem_of_match);
|
||||
+MODULE_DEVICE_TABLE(of, rpivid_mem_of_match);
|
||||
|
||||
-static struct platform_driver argon_mem_driver = {
|
||||
- .probe = argon_mem_probe,
|
||||
- .remove = argon_mem_remove,
|
||||
+static struct platform_driver rpivid_mem_driver = {
|
||||
+ .probe = rpivid_mem_probe,
|
||||
+ .remove = rpivid_mem_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
- .of_match_table = argon_mem_of_match,
|
||||
+ .of_match_table = rpivid_mem_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
-module_platform_driver(argon_mem_driver);
|
||||
+module_platform_driver(rpivid_mem_driver);
|
||||
|
||||
-MODULE_ALIAS("platform:argon-mem");
|
||||
+MODULE_ALIAS("platform:rpivid-mem");
|
||||
MODULE_LICENSE("GPL");
|
||||
-MODULE_DESCRIPTION("Driver for accessing Argon decoder registers from userspace");
|
||||
+MODULE_DESCRIPTION("Driver for accessing RPiVid decoder registers from userspace");
|
||||
MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.org>");
|
||||
diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c
|
||||
index ab1e9cbc50b1..f66f92fe28c3 100644
|
||||
--- a/drivers/mfd/bcm2835-pm.c
|
||||
+++ b/drivers/mfd/bcm2835-pm.c
|
||||
@@ -50,14 +50,14 @@ static int bcm2835_pm_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- /* Map the ARGON ASB regs if present. */
|
||||
+ /* Map the RPiVid ASB regs if present. */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||||
if (res) {
|
||||
- pm->arg_asb = devm_ioremap_resource(dev, res);
|
||||
- if (IS_ERR(pm->arg_asb)) {
|
||||
- dev_err(dev, "Failed to map ARGON ASB: %ld\n",
|
||||
- PTR_ERR(pm->arg_asb));
|
||||
- return PTR_ERR(pm->arg_asb);
|
||||
+ pm->rpivid_asb = devm_ioremap_resource(dev, res);
|
||||
+ if (IS_ERR(pm->rpivid_asb)) {
|
||||
+ dev_err(dev, "Failed to map RPiVid ASB: %ld\n",
|
||||
+ PTR_ERR(pm->rpivid_asb));
|
||||
+ return PTR_ERR(pm->rpivid_asb);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c
|
||||
index 918cf54ab9ef..05d2293e8e58 100644
|
||||
--- a/drivers/soc/bcm/bcm2835-power.c
|
||||
+++ b/drivers/soc/bcm/bcm2835-power.c
|
||||
@@ -637,15 +637,15 @@ static int bcm2835_power_probe(struct platform_device *pdev)
|
||||
power->base = pm->base;
|
||||
power->asb = pm->asb;
|
||||
|
||||
- /* 2711 hack: the new ARGON ASB took over V3D, which is our
|
||||
+ /* 2711 hack: the new RPiVid ASB took over V3D, which is our
|
||||
* only consumer of this driver so far. The old ASB seems to
|
||||
* still be present with ISP and H264 bits but no V3D, but I
|
||||
* don't know if that's real or not. The V3D is in the same
|
||||
* place in the new ASB as the old one, so just poke the new
|
||||
* one for now.
|
||||
*/
|
||||
- if (pm->arg_asb) {
|
||||
- power->asb = pm->arg_asb;
|
||||
+ if (pm->rpivid_asb) {
|
||||
+ power->asb = pm->rpivid_asb;
|
||||
power->is_2711 = true;
|
||||
}
|
||||
|
||||
diff --git a/include/linux/mfd/bcm2835-pm.h b/include/linux/mfd/bcm2835-pm.h
|
||||
index b2d157091e12..f70a810c55f7 100644
|
||||
--- a/include/linux/mfd/bcm2835-pm.h
|
||||
+++ b/include/linux/mfd/bcm2835-pm.h
|
||||
@@ -9,7 +9,7 @@ struct bcm2835_pm {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
void __iomem *asb;
|
||||
- void __iomem *arg_asb;
|
||||
+ void __iomem *rpivid_asb;
|
||||
};
|
||||
|
||||
#endif /* BCM2835_MFD_PM_H */
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
From 75f1d14cee8cfb1964cbda21a30cb030a632c3c2 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Mon, 29 Jul 2019 12:03:21 +0100
|
||||
Subject: [PATCH 740/826] driver: char: rpivid - also support legacy name
|
||||
|
||||
Provide transitional support for the previous names of
|
||||
the character devices.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
drivers/char/broadcom/rpivid-mem.c | 22 ++++++++++++++++++----
|
||||
1 file changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/char/broadcom/rpivid-mem.c b/drivers/char/broadcom/rpivid-mem.c
|
||||
index fae84c7d3cf4..e4e5fb1fb820 100644
|
||||
--- a/drivers/char/broadcom/rpivid-mem.c
|
||||
+++ b/drivers/char/broadcom/rpivid-mem.c
|
||||
@@ -66,7 +66,7 @@ static int rpivid_mem_open(struct inode *inode, struct file *file)
|
||||
int dev = iminor(inode);
|
||||
int ret = 0;
|
||||
struct rpivid_mem_priv *priv;
|
||||
- if (dev != DEVICE_MINOR)
|
||||
+ if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
|
||||
ret = -ENXIO;
|
||||
|
||||
priv = container_of(inode->i_cdev, struct rpivid_mem_priv,
|
||||
@@ -82,7 +82,7 @@ static int rpivid_mem_release(struct inode *inode, struct file *file)
|
||||
int dev = iminor(inode);
|
||||
int ret = 0;
|
||||
|
||||
- if (dev != DEVICE_MINOR)
|
||||
+ if (dev != DEVICE_MINOR && dev != DEVICE_MINOR + 1)
|
||||
ret = -ENXIO;
|
||||
|
||||
return ret;
|
||||
@@ -167,14 +167,14 @@ static int rpivid_mem_probe(struct platform_device *pdev)
|
||||
/* Create character device entries */
|
||||
|
||||
err = alloc_chrdev_region(&priv->devid,
|
||||
- DEVICE_MINOR, 1, priv->name);
|
||||
+ DEVICE_MINOR, 2, priv->name);
|
||||
if (err != 0) {
|
||||
dev_err(priv->dev, "unable to allocate device number");
|
||||
goto failed_alloc_chrdev;
|
||||
}
|
||||
cdev_init(&priv->rpivid_mem_cdev, &rpivid_mem_fops);
|
||||
priv->rpivid_mem_cdev.owner = THIS_MODULE;
|
||||
- err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 1);
|
||||
+ err = cdev_add(&priv->rpivid_mem_cdev, priv->devid, 2);
|
||||
if (err != 0) {
|
||||
dev_err(priv->dev, "unable to register device");
|
||||
goto failed_cdev_add;
|
||||
@@ -194,6 +194,20 @@ static int rpivid_mem_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(ptr_err))
|
||||
goto failed_device_create;
|
||||
|
||||
+ /* Legacy alias */
|
||||
+ {
|
||||
+ char *oldname = kstrdup(priv->name, GFP_KERNEL);
|
||||
+
|
||||
+ oldname[1] = 'a';
|
||||
+ oldname[2] = 'r';
|
||||
+ oldname[3] = 'g';
|
||||
+ oldname[4] = 'o';
|
||||
+ oldname[5] = 'n';
|
||||
+ (void)device_create(priv->class, NULL, priv->devid + 1, NULL,
|
||||
+ oldname + 1);
|
||||
+ kfree(oldname);
|
||||
+ }
|
||||
+
|
||||
dev_info(priv->dev, "%s initialised: Registers at 0x%08lx length 0x%08lx",
|
||||
priv->name, priv->regs_phys, priv->mem_window_len);
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
From dee43611031fb719b1472e14d9e90e176284d98c Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
Date: Thu, 1 Aug 2019 16:41:20 +0100
|
||||
Subject: [PATCH 741/826] hid: usb: Add device quirks for Freeway Airmouse T3
|
||||
and MX3
|
||||
|
||||
These wireless mouse/keyboard combo remote control devices specify
|
||||
multiple "wheel" events in their report descriptors. The wheel events
|
||||
are incorrectly defined and apparently map to accelerometer data, leading
|
||||
to spurious mouse scroll events being generated at an extreme rate when
|
||||
the device is moved.
|
||||
|
||||
As a workaround, use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE to mask
|
||||
feeding the extra wheel events to the input subsystem.
|
||||
|
||||
See: https://github.com/raspberrypi/firmware/issues/1189
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
---
|
||||
drivers/hid/hid-ids.h | 6 ++++++
|
||||
drivers/hid/hid-quirks.c | 2 ++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||||
index ab373a3942aa..4a643a60998f 100644
|
||||
--- a/drivers/hid/hid-ids.h
|
||||
+++ b/drivers/hid/hid-ids.h
|
||||
@@ -222,6 +222,9 @@
|
||||
#define USB_VENDOR_ID_BAANTO 0x2453
|
||||
#define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
|
||||
|
||||
+#define USB_VENDOR_ID_BEKEN 0x25a7
|
||||
+#define USB_DEVICE_ID_AIRMOUSE_T3 0x2402
|
||||
+
|
||||
#define USB_VENDOR_ID_BELKIN 0x050d
|
||||
#define USB_DEVICE_ID_FLIP_KVM 0x3201
|
||||
|
||||
@@ -1186,6 +1189,9 @@
|
||||
#define USB_VENDOR_ID_XAT 0x2505
|
||||
#define USB_DEVICE_ID_XAT_CSR 0x0220
|
||||
|
||||
+#define USB_VENDOR_ID_XENTA 0x1d57
|
||||
+#define USB_DEVICE_ID_AIRMOUSE_MX3 0xad03
|
||||
+
|
||||
#define USB_VENDOR_ID_XIN_MO 0x16c0
|
||||
#define USB_DEVICE_ID_XIN_MO_DUAL_ARCADE 0x05e1
|
||||
#define USB_DEVICE_ID_THT_2P_ARCADE 0x75e1
|
||||
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
|
||||
index 91e86af44a04..80b8c6ba8939 100644
|
||||
--- a/drivers/hid/hid-quirks.c
|
||||
+++ b/drivers/hid/hid-quirks.c
|
||||
@@ -43,6 +43,7 @@ static const struct hid_device_id hid_quirks[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_BEKEN, USB_DEVICE_ID_AIRMOUSE_T3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
|
||||
@@ -171,6 +172,7 @@ static const struct hid_device_id hid_quirks[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_XENTA, USB_DEVICE_ID_AIRMOUSE_MX3), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
From d7c5bc668cd07ccf3682e5a271375421bff915d0 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Fri, 14 Jun 2019 10:12:07 +0100
|
||||
Subject: [PATCH 742/826] drm/vc4: Add "Broadcast RGB" connector property
|
||||
|
||||
Some HDMI monitors do not abide by the full or limited
|
||||
(16-235) range RGB flags in the AVI infoframe. This can
|
||||
result in images looking washed out (if given limited and
|
||||
interpreting as full), or detail disappearing at the extremes
|
||||
(given full and interpreting as limited).
|
||||
|
||||
Copy the Intel i915 driver's approach of adding an override
|
||||
property ("Broadcast RGB") to force one mode or the other.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 190 +++++++++++++++++++++++--
|
||||
1 file changed, 177 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
index bcbd2f709c7f..8e235e65d5a8 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
@@ -285,6 +285,13 @@ to_vc4_fkms_encoder(struct drm_encoder *encoder)
|
||||
return container_of(encoder, struct vc4_fkms_encoder, base);
|
||||
}
|
||||
|
||||
+/* "Broadcast RGB" property.
|
||||
+ * Allows overriding of HDMI full or limited range RGB
|
||||
+ */
|
||||
+#define VC4_BROADCAST_RGB_AUTO 0
|
||||
+#define VC4_BROADCAST_RGB_FULL 1
|
||||
+#define VC4_BROADCAST_RGB_LIMITED 2
|
||||
+
|
||||
/* VC4 FKMS connector KMS struct */
|
||||
struct vc4_fkms_connector {
|
||||
struct drm_connector base;
|
||||
@@ -297,6 +304,8 @@ struct vc4_fkms_connector {
|
||||
struct vc4_dev *vc4_dev;
|
||||
u32 display_number;
|
||||
u32 display_type;
|
||||
+
|
||||
+ struct drm_property *broadcast_rgb_property;
|
||||
};
|
||||
|
||||
static inline struct vc4_fkms_connector *
|
||||
@@ -305,6 +314,16 @@ to_vc4_fkms_connector(struct drm_connector *connector)
|
||||
return container_of(connector, struct vc4_fkms_connector, base);
|
||||
}
|
||||
|
||||
+/* VC4 FKMS connector state */
|
||||
+struct vc4_fkms_connector_state {
|
||||
+ struct drm_connector_state base;
|
||||
+
|
||||
+ int broadcast_rgb;
|
||||
+};
|
||||
+
|
||||
+#define to_vc4_fkms_connector_state(x) \
|
||||
+ container_of(x, struct vc4_fkms_connector_state, base)
|
||||
+
|
||||
static u32 vc4_get_display_type(u32 display_number)
|
||||
{
|
||||
const u32 display_types[] = {
|
||||
@@ -832,8 +851,6 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
mode->picture_aspect_ratio, mode->flags);
|
||||
mb.timings.display = vc4_crtc->display_number;
|
||||
|
||||
- mb.timings.video_id_code = frame.avi.video_code;
|
||||
-
|
||||
mb.timings.clock = mode->clock;
|
||||
mb.timings.hdisplay = mode->hdisplay;
|
||||
mb.timings.hsync_start = mode->hsync_start;
|
||||
@@ -871,11 +888,30 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!vc4_encoder->hdmi_monitor)
|
||||
+ if (!vc4_encoder->hdmi_monitor) {
|
||||
mb.timings.flags |= TIMINGS_FLAGS_DVI;
|
||||
- else if (drm_default_rgb_quant_range(mode) ==
|
||||
+ mb.timings.video_id_code = frame.avi.video_code;
|
||||
+ } else {
|
||||
+ struct vc4_fkms_connector_state *conn_state =
|
||||
+ to_vc4_fkms_connector_state(vc4_crtc->connector->state);
|
||||
+
|
||||
+ /* Do not provide a VIC as the HDMI spec requires that we do not
|
||||
+ * signal the opposite of the defined range in the AVI
|
||||
+ * infoframe.
|
||||
+ */
|
||||
+ mb.timings.video_id_code = 0;
|
||||
+
|
||||
+ if (conn_state->broadcast_rgb == VC4_BROADCAST_RGB_AUTO) {
|
||||
+ /* See CEA-861-E - 5.1 Default Encoding Parameters */
|
||||
+ if (drm_default_rgb_quant_range(mode) ==
|
||||
HDMI_QUANTIZATION_RANGE_LIMITED)
|
||||
- mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
|
||||
+ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
|
||||
+ } else {
|
||||
+ if (conn_state->broadcast_rgb ==
|
||||
+ VC4_BROADCAST_RGB_LIMITED)
|
||||
+ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/*
|
||||
FIXME: To implement
|
||||
@@ -1340,13 +1376,95 @@ static void vc4_fkms_connector_destroy(struct drm_connector *connector)
|
||||
drm_connector_cleanup(connector);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * vc4_connector_duplicate_state - duplicate connector state
|
||||
+ * @connector: digital connector
|
||||
+ *
|
||||
+ * Allocates and returns a copy of the connector state (both common and
|
||||
+ * digital connector specific) for the specified connector.
|
||||
+ *
|
||||
+ * Returns: The newly allocated connector state, or NULL on failure.
|
||||
+ */
|
||||
+struct drm_connector_state *
|
||||
+vc4_connector_duplicate_state(struct drm_connector *connector)
|
||||
+{
|
||||
+ struct vc4_fkms_connector_state *state;
|
||||
+
|
||||
+ state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
|
||||
+ if (!state)
|
||||
+ return NULL;
|
||||
+
|
||||
+ __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
|
||||
+ return &state->base;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * vc4_connector_atomic_get_property - hook for connector->atomic_get_property.
|
||||
+ * @connector: Connector to get the property for.
|
||||
+ * @state: Connector state to retrieve the property from.
|
||||
+ * @property: Property to retrieve.
|
||||
+ * @val: Return value for the property.
|
||||
+ *
|
||||
+ * Returns the atomic property value for a digital connector.
|
||||
+ */
|
||||
+int vc4_connector_atomic_get_property(struct drm_connector *connector,
|
||||
+ const struct drm_connector_state *state,
|
||||
+ struct drm_property *property,
|
||||
+ uint64_t *val)
|
||||
+{
|
||||
+ struct vc4_fkms_connector *fkms_connector =
|
||||
+ to_vc4_fkms_connector(connector);
|
||||
+ struct vc4_fkms_connector_state *vc4_conn_state =
|
||||
+ to_vc4_fkms_connector_state(state);
|
||||
+
|
||||
+ if (property == fkms_connector->broadcast_rgb_property) {
|
||||
+ *val = vc4_conn_state->broadcast_rgb;
|
||||
+ } else {
|
||||
+ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
|
||||
+ property->base.id, property->name);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * vc4_connector_atomic_set_property - hook for connector->atomic_set_property.
|
||||
+ * @connector: Connector to set the property for.
|
||||
+ * @state: Connector state to set the property on.
|
||||
+ * @property: Property to set.
|
||||
+ * @val: New value for the property.
|
||||
+ *
|
||||
+ * Sets the atomic property value for a digital connector.
|
||||
+ */
|
||||
+int vc4_connector_atomic_set_property(struct drm_connector *connector,
|
||||
+ struct drm_connector_state *state,
|
||||
+ struct drm_property *property,
|
||||
+ uint64_t val)
|
||||
+{
|
||||
+ struct vc4_fkms_connector *fkms_connector =
|
||||
+ to_vc4_fkms_connector(connector);
|
||||
+ struct vc4_fkms_connector_state *vc4_conn_state =
|
||||
+ to_vc4_fkms_connector_state(state);
|
||||
+
|
||||
+ if (property == fkms_connector->broadcast_rgb_property) {
|
||||
+ vc4_conn_state->broadcast_rgb = val;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
|
||||
+ property->base.id, property->name);
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
|
||||
.detect = vc4_fkms_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = vc4_fkms_connector_destroy,
|
||||
- .reset = drm_atomic_helper_connector_reset,
|
||||
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
+ .atomic_duplicate_state = vc4_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
+ .atomic_get_property = vc4_connector_atomic_get_property,
|
||||
+ .atomic_set_property = vc4_connector_atomic_set_property,
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = {
|
||||
@@ -1359,12 +1477,40 @@ static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs =
|
||||
.best_encoder = vc4_fkms_connector_best_encoder,
|
||||
};
|
||||
|
||||
+static const struct drm_prop_enum_list broadcast_rgb_names[] = {
|
||||
+ { VC4_BROADCAST_RGB_AUTO, "Automatic" },
|
||||
+ { VC4_BROADCAST_RGB_FULL, "Full" },
|
||||
+ { VC4_BROADCAST_RGB_LIMITED, "Limited 16:235" },
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+vc4_attach_broadcast_rgb_property(struct vc4_fkms_connector *fkms_connector)
|
||||
+{
|
||||
+ struct drm_device *dev = fkms_connector->base.dev;
|
||||
+ struct drm_property *prop;
|
||||
+
|
||||
+ prop = fkms_connector->broadcast_rgb_property;
|
||||
+ if (!prop) {
|
||||
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
|
||||
+ "Broadcast RGB",
|
||||
+ broadcast_rgb_names,
|
||||
+ ARRAY_SIZE(broadcast_rgb_names));
|
||||
+ if (!prop)
|
||||
+ return;
|
||||
+
|
||||
+ fkms_connector->broadcast_rgb_property = prop;
|
||||
+ }
|
||||
+
|
||||
+ drm_object_attach_property(&fkms_connector->base.base, prop, 0);
|
||||
+}
|
||||
+
|
||||
static struct drm_connector *
|
||||
vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
|
||||
u32 display_num)
|
||||
{
|
||||
struct drm_connector *connector = NULL;
|
||||
struct vc4_fkms_connector *fkms_connector;
|
||||
+ struct vc4_fkms_connector_state *conn_state = NULL;
|
||||
struct vc4_dev *vc4_dev = to_vc4_dev(dev);
|
||||
int ret = 0;
|
||||
|
||||
@@ -1373,9 +1519,18 @@ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
|
||||
fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
|
||||
GFP_KERNEL);
|
||||
if (!fkms_connector) {
|
||||
- ret = -ENOMEM;
|
||||
- goto fail;
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Allocate enough memory to hold vc4_fkms_connector_state,
|
||||
+ */
|
||||
+ conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
|
||||
+ if (!conn_state) {
|
||||
+ kfree(fkms_connector);
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
+
|
||||
connector = &fkms_connector->base;
|
||||
|
||||
fkms_connector->encoder = encoder;
|
||||
@@ -1383,6 +1538,9 @@ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
|
||||
fkms_connector->display_type = vc4_get_display_type(display_num);
|
||||
fkms_connector->vc4_dev = vc4_dev;
|
||||
|
||||
+ __drm_atomic_helper_connector_reset(connector,
|
||||
+ &conn_state->base);
|
||||
+
|
||||
if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
|
||||
drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
@@ -1403,10 +1561,14 @@ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
|
||||
connector->interlace_allowed = 0;
|
||||
}
|
||||
|
||||
- /* Create and attach TV margin props to this connector. */
|
||||
- ret = drm_mode_create_tv_margin_properties(dev);
|
||||
- if (ret)
|
||||
- return ERR_PTR(ret);
|
||||
+ /* Create and attach TV margin props to this connector.
|
||||
+ * Already done for SDTV outputs.
|
||||
+ */
|
||||
+ if (fkms_connector->display_type != DRM_MODE_ENCODER_TVDAC) {
|
||||
+ ret = drm_mode_create_tv_margin_properties(dev);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
drm_connector_attach_tv_margin_properties(connector);
|
||||
|
||||
@@ -1415,6 +1577,8 @@ vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
|
||||
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
+ vc4_attach_broadcast_rgb_property(fkms_connector);
|
||||
+
|
||||
drm_connector_attach_encoder(connector, encoder);
|
||||
|
||||
return connector;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
From 1039d354cbdb917b4e532c45c65635ce7ae2a1c7 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:48 +0200
|
||||
Subject: [PATCH 743/826] drm/connector: Add documentation for drm_cmdline_mode
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
commit 772cd52c5574b04b00a97d638b2cfe94c0c1a9b6 upstream.
|
||||
|
||||
The struct drm_cmdline_mode holds the result of the command line parsers.
|
||||
However, it wasn't documented so far, so let's do that.
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/963c893c16c6a25fc469b53c726f493d99bdc578.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
include/drm/drm_connector.h | 86 ++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 84 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
|
||||
index 342a4db4b0c1..83ed80edb083 100644
|
||||
--- a/include/drm/drm_connector.h
|
||||
+++ b/include/drm/drm_connector.h
|
||||
@@ -755,18 +755,100 @@ struct drm_connector_funcs {
|
||||
const struct drm_connector_state *state);
|
||||
};
|
||||
|
||||
-/* mode specified on the command line */
|
||||
+/**
|
||||
+ * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
|
||||
+ *
|
||||
+ * Each connector can have an initial mode with additional options
|
||||
+ * passed through the kernel command line. This structure allows to
|
||||
+ * express those parameters and will be filled by the command-line
|
||||
+ * parser.
|
||||
+ */
|
||||
struct drm_cmdline_mode {
|
||||
+ /**
|
||||
+ * @specified:
|
||||
+ *
|
||||
+ * Has a mode been read from the command-line?
|
||||
+ */
|
||||
bool specified;
|
||||
+
|
||||
+ /**
|
||||
+ * @refresh_specified:
|
||||
+ *
|
||||
+ * Did the mode have a preferred refresh rate?
|
||||
+ */
|
||||
bool refresh_specified;
|
||||
+
|
||||
+ /**
|
||||
+ * @bpp_specified:
|
||||
+ *
|
||||
+ * Did the mode have a preferred BPP?
|
||||
+ */
|
||||
bool bpp_specified;
|
||||
- int xres, yres;
|
||||
+
|
||||
+ /**
|
||||
+ * @xres:
|
||||
+ *
|
||||
+ * Active resolution on the X axis, in pixels.
|
||||
+ */
|
||||
+ int xres;
|
||||
+
|
||||
+ /**
|
||||
+ * @yres:
|
||||
+ *
|
||||
+ * Active resolution on the Y axis, in pixels.
|
||||
+ */
|
||||
+ int yres;
|
||||
+
|
||||
+ /**
|
||||
+ * @bpp:
|
||||
+ *
|
||||
+ * Bits per pixels for the mode.
|
||||
+ */
|
||||
int bpp;
|
||||
+
|
||||
+ /**
|
||||
+ * @refresh:
|
||||
+ *
|
||||
+ * Refresh rate, in Hertz.
|
||||
+ */
|
||||
int refresh;
|
||||
+
|
||||
+ /**
|
||||
+ * @rb:
|
||||
+ *
|
||||
+ * Do we need to use reduced blanking?
|
||||
+ */
|
||||
bool rb;
|
||||
+
|
||||
+ /**
|
||||
+ * @interlace:
|
||||
+ *
|
||||
+ * The mode is interlaced.
|
||||
+ */
|
||||
bool interlace;
|
||||
+
|
||||
+ /**
|
||||
+ * @cvt:
|
||||
+ *
|
||||
+ * The timings will be calculated using the VESA Coordinated
|
||||
+ * Video Timings instead of looking up the mode from a table.
|
||||
+ */
|
||||
bool cvt;
|
||||
+
|
||||
+ /**
|
||||
+ * @margins:
|
||||
+ *
|
||||
+ * Add margins to the mode calculation (1.8% of xres rounded
|
||||
+ * down to 8 pixels and 1.8% of yres).
|
||||
+ */
|
||||
bool margins;
|
||||
+
|
||||
+ /**
|
||||
+ * @force:
|
||||
+ *
|
||||
+ * Ignore the hotplug state of the connector, and force its
|
||||
+ * state to one of the DRM_FORCE_* values.
|
||||
+ */
|
||||
enum drm_connector_force force;
|
||||
};
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
From 402f0b03a46f4dcaf83e89cfca8edfa9057831e1 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:49 +0200
|
||||
Subject: [PATCH 744/826] drm/modes: Rewrite the command line parser
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
commit e08ab74bd4c7a5fe311bc05f32dbb4f1e7fa3428 upstream.
|
||||
|
||||
Rewrite the command line parser in order to get away from the state machine
|
||||
parsing the video mode lines.
|
||||
|
||||
Hopefully, this will allow to extend it more easily to support named modes
|
||||
and / or properties set directly on the command line.
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/e32cd4009153b184103554009135c7bf7c9975d7.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/drm_modes.c | 325 +++++++++++++++++++++++-------------
|
||||
1 file changed, 210 insertions(+), 115 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
|
||||
index a3104d79b48f..faae19afa686 100644
|
||||
--- a/drivers/gpu/drm/drm_modes.c
|
||||
+++ b/drivers/gpu/drm/drm_modes.c
|
||||
@@ -30,6 +30,7 @@
|
||||
* authorization from the copyright holder(s) and author(s).
|
||||
*/
|
||||
|
||||
+#include <linux/ctype.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/list_sort.h>
|
||||
#include <linux/export.h>
|
||||
@@ -1414,6 +1415,151 @@ void drm_connector_list_update(struct drm_connector *connector)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_list_update);
|
||||
|
||||
+static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
|
||||
+ struct drm_cmdline_mode *mode)
|
||||
+{
|
||||
+ unsigned int bpp;
|
||||
+
|
||||
+ if (str[0] != '-')
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ str++;
|
||||
+ bpp = simple_strtol(str, end_ptr, 10);
|
||||
+ if (*end_ptr == str)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->bpp = bpp;
|
||||
+ mode->bpp_specified = true;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
|
||||
+ struct drm_cmdline_mode *mode)
|
||||
+{
|
||||
+ unsigned int refresh;
|
||||
+
|
||||
+ if (str[0] != '@')
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ str++;
|
||||
+ refresh = simple_strtol(str, end_ptr, 10);
|
||||
+ if (*end_ptr == str)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->refresh = refresh;
|
||||
+ mode->refresh_specified = true;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int drm_mode_parse_cmdline_extra(const char *str, int length,
|
||||
+ struct drm_connector *connector,
|
||||
+ struct drm_cmdline_mode *mode)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ switch (str[i]) {
|
||||
+ case 'i':
|
||||
+ mode->interlace = true;
|
||||
+ break;
|
||||
+ case 'm':
|
||||
+ mode->margins = true;
|
||||
+ break;
|
||||
+ case 'D':
|
||||
+ if (mode->force != DRM_FORCE_UNSPECIFIED)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
|
||||
+ (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
|
||||
+ mode->force = DRM_FORCE_ON;
|
||||
+ else
|
||||
+ mode->force = DRM_FORCE_ON_DIGITAL;
|
||||
+ break;
|
||||
+ case 'd':
|
||||
+ if (mode->force != DRM_FORCE_UNSPECIFIED)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->force = DRM_FORCE_OFF;
|
||||
+ break;
|
||||
+ case 'e':
|
||||
+ if (mode->force != DRM_FORCE_UNSPECIFIED)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->force = DRM_FORCE_ON;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
|
||||
+ bool extras,
|
||||
+ struct drm_connector *connector,
|
||||
+ struct drm_cmdline_mode *mode)
|
||||
+{
|
||||
+ const char *str_start = str;
|
||||
+ bool rb = false, cvt = false;
|
||||
+ int xres = 0, yres = 0;
|
||||
+ int remaining, i;
|
||||
+ char *end_ptr;
|
||||
+
|
||||
+ xres = simple_strtol(str, &end_ptr, 10);
|
||||
+ if (end_ptr == str)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (end_ptr[0] != 'x')
|
||||
+ return -EINVAL;
|
||||
+ end_ptr++;
|
||||
+
|
||||
+ str = end_ptr;
|
||||
+ yres = simple_strtol(str, &end_ptr, 10);
|
||||
+ if (end_ptr == str)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ remaining = length - (end_ptr - str_start);
|
||||
+ if (remaining < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (i = 0; i < remaining; i++) {
|
||||
+ switch (end_ptr[i]) {
|
||||
+ case 'M':
|
||||
+ cvt = true;
|
||||
+ break;
|
||||
+ case 'R':
|
||||
+ rb = true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ /*
|
||||
+ * Try to pass that to our extras parsing
|
||||
+ * function to handle the case where the
|
||||
+ * extras are directly after the resolution
|
||||
+ */
|
||||
+ if (extras) {
|
||||
+ int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
|
||||
+ 1,
|
||||
+ connector,
|
||||
+ mode);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ mode->xres = xres;
|
||||
+ mode->yres = yres;
|
||||
+ mode->cvt = cvt;
|
||||
+ mode->rb = rb;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector
|
||||
* @mode_option: optional per connector mode option
|
||||
@@ -1440,13 +1586,12 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
struct drm_cmdline_mode *mode)
|
||||
{
|
||||
const char *name;
|
||||
- unsigned int namelen;
|
||||
- bool res_specified = false, bpp_specified = false, refresh_specified = false;
|
||||
- unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
|
||||
- bool yres_specified = false, cvt = false, rb = false;
|
||||
- bool interlace = false, margins = false, was_digit = false;
|
||||
- int i;
|
||||
- enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
|
||||
+ bool parse_extras = false;
|
||||
+ unsigned int bpp_off = 0, refresh_off = 0;
|
||||
+ unsigned int mode_end = 0;
|
||||
+ char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
|
||||
+ char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
|
||||
+ int ret;
|
||||
|
||||
#ifdef CONFIG_FB
|
||||
if (!mode_option)
|
||||
@@ -1459,127 +1604,77 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
}
|
||||
|
||||
name = mode_option;
|
||||
- namelen = strlen(name);
|
||||
- for (i = namelen-1; i >= 0; i--) {
|
||||
- switch (name[i]) {
|
||||
- case '@':
|
||||
- if (!refresh_specified && !bpp_specified &&
|
||||
- !yres_specified && !cvt && !rb && was_digit) {
|
||||
- refresh = simple_strtol(&name[i+1], NULL, 10);
|
||||
- refresh_specified = true;
|
||||
- was_digit = false;
|
||||
- } else
|
||||
- goto done;
|
||||
- break;
|
||||
- case '-':
|
||||
- if (!bpp_specified && !yres_specified && !cvt &&
|
||||
- !rb && was_digit) {
|
||||
- bpp = simple_strtol(&name[i+1], NULL, 10);
|
||||
- bpp_specified = true;
|
||||
- was_digit = false;
|
||||
- } else
|
||||
- goto done;
|
||||
- break;
|
||||
- case 'x':
|
||||
- if (!yres_specified && was_digit) {
|
||||
- yres = simple_strtol(&name[i+1], NULL, 10);
|
||||
- yres_specified = true;
|
||||
- was_digit = false;
|
||||
- } else
|
||||
- goto done;
|
||||
- break;
|
||||
- case '0' ... '9':
|
||||
- was_digit = true;
|
||||
- break;
|
||||
- case 'M':
|
||||
- if (yres_specified || cvt || was_digit)
|
||||
- goto done;
|
||||
- cvt = true;
|
||||
- break;
|
||||
- case 'R':
|
||||
- if (yres_specified || cvt || rb || was_digit)
|
||||
- goto done;
|
||||
- rb = true;
|
||||
- break;
|
||||
- case 'm':
|
||||
- if (cvt || yres_specified || was_digit)
|
||||
- goto done;
|
||||
- margins = true;
|
||||
- break;
|
||||
- case 'i':
|
||||
- if (cvt || yres_specified || was_digit)
|
||||
- goto done;
|
||||
- interlace = true;
|
||||
- break;
|
||||
- case 'e':
|
||||
- if (yres_specified || bpp_specified || refresh_specified ||
|
||||
- was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||
- goto done;
|
||||
|
||||
- force = DRM_FORCE_ON;
|
||||
- break;
|
||||
- case 'D':
|
||||
- if (yres_specified || bpp_specified || refresh_specified ||
|
||||
- was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||
- goto done;
|
||||
+ if (!isdigit(name[0]))
|
||||
+ return false;
|
||||
|
||||
- if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
|
||||
- (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
|
||||
- force = DRM_FORCE_ON;
|
||||
- else
|
||||
- force = DRM_FORCE_ON_DIGITAL;
|
||||
- break;
|
||||
- case 'd':
|
||||
- if (yres_specified || bpp_specified || refresh_specified ||
|
||||
- was_digit || (force != DRM_FORCE_UNSPECIFIED))
|
||||
- goto done;
|
||||
+ /* Try to locate the bpp and refresh specifiers, if any */
|
||||
+ bpp_ptr = strchr(name, '-');
|
||||
+ if (bpp_ptr) {
|
||||
+ bpp_off = bpp_ptr - name;
|
||||
+ mode->bpp_specified = true;
|
||||
+ }
|
||||
|
||||
- force = DRM_FORCE_OFF;
|
||||
- break;
|
||||
- default:
|
||||
- goto done;
|
||||
- }
|
||||
+ refresh_ptr = strchr(name, '@');
|
||||
+ if (refresh_ptr) {
|
||||
+ refresh_off = refresh_ptr - name;
|
||||
+ mode->refresh_specified = true;
|
||||
}
|
||||
|
||||
- if (i < 0 && yres_specified) {
|
||||
- char *ch;
|
||||
- xres = simple_strtol(name, &ch, 10);
|
||||
- if ((ch != NULL) && (*ch == 'x'))
|
||||
- res_specified = true;
|
||||
- else
|
||||
- i = ch - name;
|
||||
- } else if (!yres_specified && was_digit) {
|
||||
- /* catch mode that begins with digits but has no 'x' */
|
||||
- i = 0;
|
||||
+ /* Locate the end of the name / resolution, and parse it */
|
||||
+ if (bpp_ptr && refresh_ptr) {
|
||||
+ mode_end = min(bpp_off, refresh_off);
|
||||
+ } else if (bpp_ptr) {
|
||||
+ mode_end = bpp_off;
|
||||
+ } else if (refresh_ptr) {
|
||||
+ mode_end = refresh_off;
|
||||
+ } else {
|
||||
+ mode_end = strlen(name);
|
||||
+ parse_extras = true;
|
||||
}
|
||||
-done:
|
||||
- if (i >= 0) {
|
||||
- pr_warn("[drm] parse error at position %i in video mode '%s'\n",
|
||||
- i, name);
|
||||
- mode->specified = false;
|
||||
+
|
||||
+ ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
|
||||
+ parse_extras,
|
||||
+ connector,
|
||||
+ mode);
|
||||
+ if (ret)
|
||||
return false;
|
||||
- }
|
||||
+ mode->specified = true;
|
||||
|
||||
- if (res_specified) {
|
||||
- mode->specified = true;
|
||||
- mode->xres = xres;
|
||||
- mode->yres = yres;
|
||||
+ if (bpp_ptr) {
|
||||
+ ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
|
||||
+ if (ret)
|
||||
+ return false;
|
||||
}
|
||||
|
||||
- if (refresh_specified) {
|
||||
- mode->refresh_specified = true;
|
||||
- mode->refresh = refresh;
|
||||
+ if (refresh_ptr) {
|
||||
+ ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
|
||||
+ &refresh_end_ptr, mode);
|
||||
+ if (ret)
|
||||
+ return false;
|
||||
}
|
||||
|
||||
- if (bpp_specified) {
|
||||
- mode->bpp_specified = true;
|
||||
- mode->bpp = bpp;
|
||||
+ /*
|
||||
+ * Locate the end of the bpp / refresh, and parse the extras
|
||||
+ * if relevant
|
||||
+ */
|
||||
+ if (bpp_ptr && refresh_ptr)
|
||||
+ extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
|
||||
+ else if (bpp_ptr)
|
||||
+ extra_ptr = bpp_end_ptr;
|
||||
+ else if (refresh_ptr)
|
||||
+ extra_ptr = refresh_end_ptr;
|
||||
+
|
||||
+ if (extra_ptr) {
|
||||
+ int remaining = strlen(name) - (extra_ptr - name);
|
||||
+
|
||||
+ /*
|
||||
+ * We still have characters to process, while
|
||||
+ * we shouldn't have any
|
||||
+ */
|
||||
+ if (remaining > 0)
|
||||
+ return false;
|
||||
}
|
||||
- mode->rb = rb;
|
||||
- mode->cvt = cvt;
|
||||
- mode->interlace = interlace;
|
||||
- mode->margins = margins;
|
||||
- mode->force = force;
|
||||
|
||||
return true;
|
||||
}
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
From 5329799326fa5bab28d5cbc9c8bb045478f24ba2 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:50 +0200
|
||||
Subject: [PATCH 745/826] drm/modes: Support modes names on the command line
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
commit 3aeeb13d899627fe2b86bdbdcd0927cf7192234f upstream.
|
||||
Minor conflict resolution as upstream has moved functions
|
||||
from drm_fb_helper.c to a new drm_client_modeset.c
|
||||
|
||||
The drm subsystem also uses the video= kernel parameter, and in the
|
||||
documentation refers to the fbdev documentation for that parameter.
|
||||
|
||||
However, that documentation also says that instead of giving the mode using
|
||||
its resolution we can also give a name. However, DRM doesn't handle that
|
||||
case at the moment. Even though in most case it shouldn't make any
|
||||
difference, it might be useful for analog modes, where different standards
|
||||
might have the same resolution, but still have a few different parameters
|
||||
that are not encoded in the modes (NTSC vs NTSC-J vs PAL-M for example).
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/18443e0c3bdbbd16cea4ec63bc7f2079b820b43b.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/drm_connector.c | 3 +-
|
||||
drivers/gpu/drm/drm_fb_helper.c | 4 +++
|
||||
drivers/gpu/drm/drm_modes.c | 62 ++++++++++++++++++++++++---------
|
||||
include/drm/drm_connector.h | 7 ++++
|
||||
4 files changed, 59 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
|
||||
index bbc3f3ed47a8..ff0996f49b21 100644
|
||||
--- a/drivers/gpu/drm/drm_connector.c
|
||||
+++ b/drivers/gpu/drm/drm_connector.c
|
||||
@@ -135,8 +135,9 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
|
||||
connector->force = mode->force;
|
||||
}
|
||||
|
||||
- DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
|
||||
+ DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
|
||||
connector->name,
|
||||
+ mode->name ? mode->name : "",
|
||||
mode->xres, mode->yres,
|
||||
mode->refresh_specified ? mode->refresh : 60,
|
||||
mode->rb ? " reduced blanking" : "",
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index 8b546fde139d..c8a8e0d7212d 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -2099,6 +2099,10 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
|
||||
prefer_non_interlace = !cmdline_mode->interlace;
|
||||
again:
|
||||
list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
|
||||
+ /* Check (optional) mode name first */
|
||||
+ if (!strcmp(mode->name, cmdline_mode->name))
|
||||
+ return mode;
|
||||
+
|
||||
/* check width/height */
|
||||
if (mode->hdisplay != cmdline_mode->xres ||
|
||||
mode->vdisplay != cmdline_mode->yres)
|
||||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
|
||||
index faae19afa686..c6ce1d526b10 100644
|
||||
--- a/drivers/gpu/drm/drm_modes.c
|
||||
+++ b/drivers/gpu/drm/drm_modes.c
|
||||
@@ -1586,7 +1586,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
struct drm_cmdline_mode *mode)
|
||||
{
|
||||
const char *name;
|
||||
- bool parse_extras = false;
|
||||
+ bool named_mode = false, parse_extras = false;
|
||||
unsigned int bpp_off = 0, refresh_off = 0;
|
||||
unsigned int mode_end = 0;
|
||||
char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
|
||||
@@ -1605,8 +1605,22 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
|
||||
name = mode_option;
|
||||
|
||||
- if (!isdigit(name[0]))
|
||||
- return false;
|
||||
+ /*
|
||||
+ * This is a bit convoluted. To differentiate between the
|
||||
+ * named modes and poorly formatted resolutions, we need a
|
||||
+ * bunch of things:
|
||||
+ * - We need to make sure that the first character (which
|
||||
+ * would be our resolution in X) is a digit.
|
||||
+ * - However, if the X resolution is missing, then we end up
|
||||
+ * with something like x<yres>, with our first character
|
||||
+ * being an alpha-numerical character, which would be
|
||||
+ * considered a named mode.
|
||||
+ *
|
||||
+ * If this isn't enough, we should add more heuristics here,
|
||||
+ * and matching unit-tests.
|
||||
+ */
|
||||
+ if (!isdigit(name[0]) && name[0] != 'x')
|
||||
+ named_mode = true;
|
||||
|
||||
/* Try to locate the bpp and refresh specifiers, if any */
|
||||
bpp_ptr = strchr(name, '-');
|
||||
@@ -1617,6 +1631,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
|
||||
refresh_ptr = strchr(name, '@');
|
||||
if (refresh_ptr) {
|
||||
+ if (named_mode)
|
||||
+ return false;
|
||||
+
|
||||
refresh_off = refresh_ptr - name;
|
||||
mode->refresh_specified = true;
|
||||
}
|
||||
@@ -1633,12 +1650,16 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
parse_extras = true;
|
||||
}
|
||||
|
||||
- ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
|
||||
- parse_extras,
|
||||
- connector,
|
||||
- mode);
|
||||
- if (ret)
|
||||
- return false;
|
||||
+ if (named_mode) {
|
||||
+ strncpy(mode->name, name, mode_end);
|
||||
+ } else {
|
||||
+ ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
|
||||
+ parse_extras,
|
||||
+ connector,
|
||||
+ mode);
|
||||
+ if (ret)
|
||||
+ return false;
|
||||
+ }
|
||||
mode->specified = true;
|
||||
|
||||
if (bpp_ptr) {
|
||||
@@ -1666,14 +1687,23 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
extra_ptr = refresh_end_ptr;
|
||||
|
||||
if (extra_ptr) {
|
||||
- int remaining = strlen(name) - (extra_ptr - name);
|
||||
+ if (!named_mode) {
|
||||
+ int len = strlen(name) - (extra_ptr - name);
|
||||
|
||||
- /*
|
||||
- * We still have characters to process, while
|
||||
- * we shouldn't have any
|
||||
- */
|
||||
- if (remaining > 0)
|
||||
- return false;
|
||||
+ ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
|
||||
+ connector, mode);
|
||||
+ if (ret)
|
||||
+ return false;
|
||||
+ } else {
|
||||
+ int remaining = strlen(name) - (extra_ptr - name);
|
||||
+
|
||||
+ /*
|
||||
+ * We still have characters to process, while
|
||||
+ * we shouldn't have any
|
||||
+ */
|
||||
+ if (remaining > 0)
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
|
||||
return true;
|
||||
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
|
||||
index 83ed80edb083..9ffd8e931ee0 100644
|
||||
--- a/include/drm/drm_connector.h
|
||||
+++ b/include/drm/drm_connector.h
|
||||
@@ -764,6 +764,13 @@ struct drm_connector_funcs {
|
||||
* parser.
|
||||
*/
|
||||
struct drm_cmdline_mode {
|
||||
+ /**
|
||||
+ * @name:
|
||||
+ *
|
||||
+ * Name of the mode.
|
||||
+ */
|
||||
+ char name[DRM_DISPLAY_MODE_LEN];
|
||||
+
|
||||
/**
|
||||
* @specified:
|
||||
*
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
From 119273663afb44806748f42af20333ce8b6cfa08 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:51 +0200
|
||||
Subject: [PATCH 746/826] drm/modes: Allow to specify rotation and reflection
|
||||
on the commandline
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Commit 1bf4e09227c345e246062285eba4b8fe660e512e upstream.
|
||||
Minor conflict resolution as upstream has moved functions
|
||||
from drm_fb_helper.c to a new drm_client_modeset.c
|
||||
|
||||
Rotations and reflections setup are needed in some scenarios to initialise
|
||||
properly the initial framebuffer. Some drivers already had a bunch of
|
||||
quirks to deal with this, such as either a private kernel command line
|
||||
parameter (omapdss) or on the device tree (various panels).
|
||||
|
||||
In order to accomodate this, let's create a video mode parameter to deal
|
||||
with the rotation and reflexion.
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/777da16e42db757c1f5b414b5ca34507097fed5c.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
Documentation/fb/modedb.txt | 12 ++++
|
||||
drivers/gpu/drm/drm_fb_helper.c | 30 +++++++++
|
||||
drivers/gpu/drm/drm_modes.c | 114 ++++++++++++++++++++++++++------
|
||||
include/drm/drm_connector.h | 10 +++
|
||||
4 files changed, 146 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/Documentation/fb/modedb.txt b/Documentation/fb/modedb.txt
|
||||
index 16aa08453911..52418c6dbfc4 100644
|
||||
--- a/Documentation/fb/modedb.txt
|
||||
+++ b/Documentation/fb/modedb.txt
|
||||
@@ -51,6 +51,18 @@ To force the VGA output to be enabled and drive a specific mode say:
|
||||
Specifying the option multiple times for different ports is possible, e.g.:
|
||||
video=LVDS-1:d video=HDMI-1:D
|
||||
|
||||
+Options can also be passed after the mode, using commas as separator.
|
||||
+
|
||||
+ Sample usage: 720x480,rotate=180 - 720x480 mode, rotated by 180 degrees
|
||||
+
|
||||
+Valid options are:
|
||||
+
|
||||
+ - reflect_x (boolean): Perform an axial symmetry on the X axis
|
||||
+ - reflect_y (boolean): Perform an axial symmetry on the Y axis
|
||||
+ - rotate (integer): Rotate the initial framebuffer by x
|
||||
+ degrees. Valid values are 0, 90, 180 and 270.
|
||||
+
|
||||
+
|
||||
***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
|
||||
|
||||
What is the VESA(TM) Coordinated Video Timings (CVT)?
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index c8a8e0d7212d..cfa272fab56a 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -2464,6 +2464,7 @@ static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_plane *plane = fb_crtc->mode_set.crtc->primary;
|
||||
+ struct drm_cmdline_mode *cmdline;
|
||||
uint64_t valid_mask = 0;
|
||||
int i, rotation;
|
||||
|
||||
@@ -2483,6 +2484,35 @@ static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
|
||||
rotation = DRM_MODE_ROTATE_0;
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * The panel already defined the default rotation
|
||||
+ * through its orientation. Whatever has been provided
|
||||
+ * on the command line needs to be added to that.
|
||||
+ *
|
||||
+ * Unfortunately, the rotations are at different bit
|
||||
+ * indices, so the math to add them up are not as
|
||||
+ * trivial as they could.
|
||||
+ *
|
||||
+ * Reflections on the other hand are pretty trivial to deal with, a
|
||||
+ * simple XOR between the two handle the addition nicely.
|
||||
+ */
|
||||
+ cmdline = &connector->cmdline_mode;
|
||||
+ if (cmdline->specified) {
|
||||
+ unsigned int cmdline_rest, panel_rest;
|
||||
+ unsigned int cmdline_rot, panel_rot;
|
||||
+ unsigned int sum_rot, sum_rest;
|
||||
+
|
||||
+ panel_rot = ilog2(rotation & DRM_MODE_ROTATE_MASK);
|
||||
+ cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
|
||||
+ sum_rot = (panel_rot + cmdline_rot) % 4;
|
||||
+
|
||||
+ panel_rest = rotation & ~DRM_MODE_ROTATE_MASK;
|
||||
+ cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK;
|
||||
+ sum_rest = panel_rest ^ cmdline_rest;
|
||||
+
|
||||
+ rotation = (1 << sum_rot) | sum_rest;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* TODO: support 90 / 270 degree hardware rotation,
|
||||
* depending on the hardware this may require the framebuffer
|
||||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
|
||||
index c6ce1d526b10..b5eed64d7349 100644
|
||||
--- a/drivers/gpu/drm/drm_modes.c
|
||||
+++ b/drivers/gpu/drm/drm_modes.c
|
||||
@@ -1560,6 +1560,71 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int drm_mode_parse_cmdline_options(char *str, size_t len,
|
||||
+ struct drm_connector *connector,
|
||||
+ struct drm_cmdline_mode *mode)
|
||||
+{
|
||||
+ unsigned int rotation = 0;
|
||||
+ char *sep = str;
|
||||
+
|
||||
+ while ((sep = strchr(sep, ','))) {
|
||||
+ char *delim, *option;
|
||||
+
|
||||
+ option = sep + 1;
|
||||
+ delim = strchr(option, '=');
|
||||
+ if (!delim) {
|
||||
+ delim = strchr(option, ',');
|
||||
+
|
||||
+ if (!delim)
|
||||
+ delim = str + len;
|
||||
+ }
|
||||
+
|
||||
+ if (!strncmp(option, "rotate", delim - option)) {
|
||||
+ const char *value = delim + 1;
|
||||
+ unsigned int deg;
|
||||
+
|
||||
+ deg = simple_strtol(value, &sep, 10);
|
||||
+
|
||||
+ /* Make sure we have parsed something */
|
||||
+ if (sep == value)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ switch (deg) {
|
||||
+ case 0:
|
||||
+ rotation |= DRM_MODE_ROTATE_0;
|
||||
+ break;
|
||||
+
|
||||
+ case 90:
|
||||
+ rotation |= DRM_MODE_ROTATE_90;
|
||||
+ break;
|
||||
+
|
||||
+ case 180:
|
||||
+ rotation |= DRM_MODE_ROTATE_180;
|
||||
+ break;
|
||||
+
|
||||
+ case 270:
|
||||
+ rotation |= DRM_MODE_ROTATE_270;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ } else if (!strncmp(option, "reflect_x", delim - option)) {
|
||||
+ rotation |= DRM_MODE_REFLECT_X;
|
||||
+ sep = delim;
|
||||
+ } else if (!strncmp(option, "reflect_y", delim - option)) {
|
||||
+ rotation |= DRM_MODE_REFLECT_Y;
|
||||
+ sep = delim;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ mode->rotation_reflection = rotation;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector
|
||||
* @mode_option: optional per connector mode option
|
||||
@@ -1575,6 +1640,10 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
|
||||
*
|
||||
* <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
|
||||
*
|
||||
+ * Additionals options can be provided following the mode, using a comma to
|
||||
+ * separate each option. Valid options can be found in
|
||||
+ * Documentation/fb/modedb.txt.
|
||||
+ *
|
||||
* The intermediate drm_cmdline_mode structure is required to store additional
|
||||
* options from the command line modline like the force-enable/disable flag.
|
||||
*
|
||||
@@ -1587,9 +1656,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
{
|
||||
const char *name;
|
||||
bool named_mode = false, parse_extras = false;
|
||||
- unsigned int bpp_off = 0, refresh_off = 0;
|
||||
+ unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
|
||||
unsigned int mode_end = 0;
|
||||
char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
|
||||
+ char *options_ptr = NULL;
|
||||
char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
|
||||
int ret;
|
||||
|
||||
@@ -1638,13 +1708,18 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
mode->refresh_specified = true;
|
||||
}
|
||||
|
||||
+ /* Locate the start of named options */
|
||||
+ options_ptr = strchr(name, ',');
|
||||
+ if (options_ptr)
|
||||
+ options_off = options_ptr - name;
|
||||
+
|
||||
/* Locate the end of the name / resolution, and parse it */
|
||||
- if (bpp_ptr && refresh_ptr) {
|
||||
- mode_end = min(bpp_off, refresh_off);
|
||||
- } else if (bpp_ptr) {
|
||||
+ if (bpp_ptr) {
|
||||
mode_end = bpp_off;
|
||||
} else if (refresh_ptr) {
|
||||
mode_end = refresh_off;
|
||||
+ } else if (options_ptr) {
|
||||
+ mode_end = options_off;
|
||||
} else {
|
||||
mode_end = strlen(name);
|
||||
parse_extras = true;
|
||||
@@ -1686,24 +1761,23 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
||||
else if (refresh_ptr)
|
||||
extra_ptr = refresh_end_ptr;
|
||||
|
||||
- if (extra_ptr) {
|
||||
- if (!named_mode) {
|
||||
- int len = strlen(name) - (extra_ptr - name);
|
||||
+ if (extra_ptr &&
|
||||
+ extra_ptr != options_ptr) {
|
||||
+ int len = strlen(name) - (extra_ptr - name);
|
||||
|
||||
- ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
|
||||
- connector, mode);
|
||||
- if (ret)
|
||||
- return false;
|
||||
- } else {
|
||||
- int remaining = strlen(name) - (extra_ptr - name);
|
||||
+ ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
|
||||
+ connector, mode);
|
||||
+ if (ret)
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * We still have characters to process, while
|
||||
- * we shouldn't have any
|
||||
- */
|
||||
- if (remaining > 0)
|
||||
- return false;
|
||||
- }
|
||||
+ if (options_ptr) {
|
||||
+ int len = strlen(name) - (options_ptr - name);
|
||||
+
|
||||
+ ret = drm_mode_parse_cmdline_options(options_ptr, len,
|
||||
+ connector, mode);
|
||||
+ if (ret)
|
||||
+ return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
|
||||
index 9ffd8e931ee0..37e9bae30224 100644
|
||||
--- a/include/drm/drm_connector.h
|
||||
+++ b/include/drm/drm_connector.h
|
||||
@@ -857,6 +857,16 @@ struct drm_cmdline_mode {
|
||||
* state to one of the DRM_FORCE_* values.
|
||||
*/
|
||||
enum drm_connector_force force;
|
||||
+
|
||||
+ /**
|
||||
+ * @rotation_reflection:
|
||||
+ *
|
||||
+ * Initial rotation and reflection of the mode setup from the
|
||||
+ * command line. See DRM_MODE_ROTATE_* and
|
||||
+ * DRM_MODE_REFLECT_*. The only rotations supported are
|
||||
+ * DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
|
||||
+ */
|
||||
+ unsigned int rotation_reflection;
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
From e5f25780cd3af08542c64fbdbe4d266b6e355b7d Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:51 +0200
|
||||
Subject: [PATCH 747/826] drm/connector: Introduce a TV margins structure
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Commit 22045e8e52bd802f743f0471242782fc3b479707 upstream.
|
||||
|
||||
The TV margins has been defined as a structure inside the
|
||||
drm_connector_state structure so far. However, we will need it in other
|
||||
structures as well, so let's move that structure definition so that it can
|
||||
be reused.
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/38b773b03f15ec7a135cdf8f7db669e5ada20cf2.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
include/drm/drm_connector.h | 41 +++++++++++++++++++++++++++----------
|
||||
1 file changed, 30 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
|
||||
index 37e9bae30224..7789fbf785e9 100644
|
||||
--- a/include/drm/drm_connector.h
|
||||
+++ b/include/drm/drm_connector.h
|
||||
@@ -343,14 +343,38 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
|
||||
const u32 *formats,
|
||||
unsigned int num_formats);
|
||||
|
||||
+/**
|
||||
+ * struct drm_connector_tv_margins - TV connector related margins
|
||||
+ *
|
||||
+ * Describes the margins in pixels to put around the image on TV
|
||||
+ * connectors to deal with overscan.
|
||||
+ */
|
||||
+struct drm_connector_tv_margins {
|
||||
+ /**
|
||||
+ * @bottom: Bottom margin in pixels.
|
||||
+ */
|
||||
+ unsigned int bottom;
|
||||
+
|
||||
+ /**
|
||||
+ * @left: Left margin in pixels.
|
||||
+ */
|
||||
+ unsigned int left;
|
||||
+
|
||||
+ /**
|
||||
+ * @right: Right margin in pixels.
|
||||
+ */
|
||||
+ unsigned int right;
|
||||
+
|
||||
+ /**
|
||||
+ * @top: Top margin in pixels.
|
||||
+ */
|
||||
+ unsigned int top;
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct drm_tv_connector_state - TV connector related states
|
||||
* @subconnector: selected subconnector
|
||||
- * @margins: margins (all margins are expressed in pixels)
|
||||
- * @margins.left: left margin
|
||||
- * @margins.right: right margin
|
||||
- * @margins.top: top margin
|
||||
- * @margins.bottom: bottom margin
|
||||
+ * @margins: TV margins
|
||||
* @mode: TV mode
|
||||
* @brightness: brightness in percent
|
||||
* @contrast: contrast in percent
|
||||
@@ -361,12 +385,7 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
|
||||
*/
|
||||
struct drm_tv_connector_state {
|
||||
enum drm_mode_subconnector subconnector;
|
||||
- struct {
|
||||
- unsigned int left;
|
||||
- unsigned int right;
|
||||
- unsigned int top;
|
||||
- unsigned int bottom;
|
||||
- } margins;
|
||||
+ struct drm_connector_tv_margins margins;
|
||||
unsigned int mode;
|
||||
unsigned int brightness;
|
||||
unsigned int contrast;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
From 43e6a2a4ce7bf5fc75a4dcad706cca33db8d7e7e Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:51 +0200
|
||||
Subject: [PATCH 748/826] drm/modes: Parse overscan properties
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Commit 3d46a3007cd8f73bae502bf5c171977b91d7aacc upstream.
|
||||
|
||||
Properly configuring the overscan properties might be needed for the
|
||||
initial setup of the framebuffer for display that still have overscan.
|
||||
Let's allow for more properties on the kernel command line to setup each
|
||||
margin.
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/e481f1628e3768ca49226ec2115cfa4dfcbd5e4c.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
Documentation/fb/modedb.txt | 2 ++
|
||||
drivers/gpu/drm/drm_modes.c | 44 +++++++++++++++++++++++++++++++++++++
|
||||
include/drm/drm_connector.h | 5 +++++
|
||||
3 files changed, 51 insertions(+)
|
||||
|
||||
diff --git a/Documentation/fb/modedb.txt b/Documentation/fb/modedb.txt
|
||||
index 52418c6dbfc4..1dd5a52f9390 100644
|
||||
--- a/Documentation/fb/modedb.txt
|
||||
+++ b/Documentation/fb/modedb.txt
|
||||
@@ -57,6 +57,8 @@ Options can also be passed after the mode, using commas as separator.
|
||||
|
||||
Valid options are:
|
||||
|
||||
+ - margin_top, margin_bottom, margin_left, margin_right (integer):
|
||||
+ Number of pixels in the margins, typically to deal with overscan on TVs
|
||||
- reflect_x (boolean): Perform an axial symmetry on the X axis
|
||||
- reflect_y (boolean): Perform an axial symmetry on the Y axis
|
||||
- rotate (integer): Rotate the initial framebuffer by x
|
||||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
|
||||
index b5eed64d7349..243de91ee9ee 100644
|
||||
--- a/drivers/gpu/drm/drm_modes.c
|
||||
+++ b/drivers/gpu/drm/drm_modes.c
|
||||
@@ -1615,6 +1615,50 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
|
||||
} else if (!strncmp(option, "reflect_y", delim - option)) {
|
||||
rotation |= DRM_MODE_REFLECT_Y;
|
||||
sep = delim;
|
||||
+ } else if (!strncmp(option, "margin_right", delim - option)) {
|
||||
+ const char *value = delim + 1;
|
||||
+ unsigned int margin;
|
||||
+
|
||||
+ margin = simple_strtol(value, &sep, 10);
|
||||
+
|
||||
+ /* Make sure we have parsed something */
|
||||
+ if (sep == value)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->tv_margins.right = margin;
|
||||
+ } else if (!strncmp(option, "margin_left", delim - option)) {
|
||||
+ const char *value = delim + 1;
|
||||
+ unsigned int margin;
|
||||
+
|
||||
+ margin = simple_strtol(value, &sep, 10);
|
||||
+
|
||||
+ /* Make sure we have parsed something */
|
||||
+ if (sep == value)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->tv_margins.left = margin;
|
||||
+ } else if (!strncmp(option, "margin_top", delim - option)) {
|
||||
+ const char *value = delim + 1;
|
||||
+ unsigned int margin;
|
||||
+
|
||||
+ margin = simple_strtol(value, &sep, 10);
|
||||
+
|
||||
+ /* Make sure we have parsed something */
|
||||
+ if (sep == value)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->tv_margins.top = margin;
|
||||
+ } else if (!strncmp(option, "margin_bottom", delim - option)) {
|
||||
+ const char *value = delim + 1;
|
||||
+ unsigned int margin;
|
||||
+
|
||||
+ margin = simple_strtol(value, &sep, 10);
|
||||
+
|
||||
+ /* Make sure we have parsed something */
|
||||
+ if (sep == value)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mode->tv_margins.bottom = margin;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
|
||||
index 7789fbf785e9..6712a934c051 100644
|
||||
--- a/include/drm/drm_connector.h
|
||||
+++ b/include/drm/drm_connector.h
|
||||
@@ -886,6 +886,11 @@ struct drm_cmdline_mode {
|
||||
* DRM_MODE_ROTATE_0 and DRM_MODE_ROTATE_180.
|
||||
*/
|
||||
unsigned int rotation_reflection;
|
||||
+
|
||||
+ /**
|
||||
+ * @tv_margins: TV margins to apply to the mode.
|
||||
+ */
|
||||
+ struct drm_connector_tv_margins tv_margins;
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
From c26132f177c3417531b80d1c3984c10a48e513e6 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:52 +0200
|
||||
Subject: [PATCH 749/826] drm/atomic: Add a function to reset connector TV
|
||||
properties
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Commit 731514b446fe6748d5a55a3dff202efb45c7d8df upstream.
|
||||
Reworked as functions have been moved from drm_atomic_helper.[c|h]
|
||||
to drm_atomic_state_helper.[c|h].
|
||||
|
||||
During the connector reset, if that connector has a TV property, it needs
|
||||
to be reset to the value provided on the command line.
|
||||
|
||||
Provide a helper to do that.
|
||||
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/84a7b657f09303a2850e1cc79e68f623547f3fdd.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/drm_atomic_helper.c | 18 ++++++++++++++++++
|
||||
include/drm/drm_atomic_helper.h | 1 +
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
|
||||
index c22062cc9992..2f416b283ef8 100644
|
||||
--- a/drivers/gpu/drm/drm_atomic_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_atomic_helper.c
|
||||
@@ -3736,6 +3736,24 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
|
||||
|
||||
+/**
|
||||
+ * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
|
||||
+ * @connector: DRM connector
|
||||
+ *
|
||||
+ * Resets the TV-related properties attached to a connector.
|
||||
+ */
|
||||
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
|
||||
+{
|
||||
+ struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
|
||||
+ struct drm_connector_state *state = connector->state;
|
||||
+
|
||||
+ state->tv.margins.left = cmdline->tv_margins.left;
|
||||
+ state->tv.margins.right = cmdline->tv_margins.right;
|
||||
+ state->tv.margins.top = cmdline->tv_margins.top;
|
||||
+ state->tv.margins.bottom = cmdline->tv_margins.bottom;
|
||||
+}
|
||||
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
|
||||
+
|
||||
/**
|
||||
* __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
|
||||
* @connector: connector object
|
||||
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
|
||||
index 99e2a5297c69..f88752489d0c 100644
|
||||
--- a/include/drm/drm_atomic_helper.h
|
||||
+++ b/include/drm/drm_atomic_helper.h
|
||||
@@ -168,6 +168,7 @@ void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
||||
void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
|
||||
struct drm_connector_state *conn_state);
|
||||
void drm_atomic_helper_connector_reset(struct drm_connector *connector);
|
||||
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
|
||||
void
|
||||
__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
|
||||
struct drm_connector_state *state);
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
From d217f5cdcef652124a39e318cde98bfdfa677a74 Mon Sep 17 00:00:00 2001
|
||||
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Date: Wed, 19 Jun 2019 12:17:53 +0200
|
||||
Subject: [PATCH 750/826] drm/vc4: hdmi: Set default state margin at reset
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Now that the TV margins are properly parsed and filled into
|
||||
drm_cmdline_mode, we just need to initialise the first state at reset to
|
||||
get those values and start using them.
|
||||
|
||||
Acked-by: Eric Anholt <eric@anholt.net>
|
||||
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||||
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/44e24172e300be6a41578517021ef6a6e90ed682.1560783090.git-series.maxime.ripard@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||
index be80769d7b5b..9dc0fc6b8a2a 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||||
@@ -292,11 +292,17 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void vc4_hdmi_connector_reset(struct drm_connector *connector)
|
||||
+{
|
||||
+ drm_atomic_helper_connector_reset(connector);
|
||||
+ drm_atomic_helper_connector_tv_reset(connector);
|
||||
+}
|
||||
+
|
||||
static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
|
||||
.detect = vc4_hdmi_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = vc4_hdmi_connector_destroy,
|
||||
- .reset = drm_atomic_helper_connector_reset,
|
||||
+ .reset = vc4_hdmi_connector_reset,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
From 884c11bacd3baf9da45f540ec4ad17ea49accfb1 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Tue, 23 Jul 2019 11:09:26 +0100
|
||||
Subject: [PATCH 751/826] drm/vc4: fkms: Set default state margin at reset
|
||||
|
||||
Now that the TV margins are properly parsed and filled into
|
||||
drm_cmdline_mode, we just need to initialise the first state at reset to
|
||||
get those values and start using them.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
index 8e235e65d5a8..066f6d17db97 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
@@ -1457,10 +1457,17 @@ int vc4_connector_atomic_set_property(struct drm_connector *connector,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+static void vc4_hdmi_connector_reset(struct drm_connector *connector)
|
||||
+{
|
||||
+ drm_atomic_helper_connector_reset(connector);
|
||||
+ drm_atomic_helper_connector_tv_reset(connector);
|
||||
+}
|
||||
+
|
||||
static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
|
||||
.detect = vc4_fkms_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = vc4_fkms_connector_destroy,
|
||||
+ .reset = vc4_hdmi_connector_reset,
|
||||
.atomic_duplicate_state = vc4_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_get_property = vc4_connector_atomic_get_property,
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
From bb0b99b86606be0ef3f7426ed3eb7d09deba3514 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Tue, 23 Jul 2019 14:10:31 +0100
|
||||
Subject: [PATCH 752/826] drm/modes: Don't apply cmdline's rotation if it
|
||||
wasn't specified
|
||||
|
||||
Taken from the dri-devel mailing list (11/7/2019) to fixup the cmdline
|
||||
parsing, but requires changes as things have moved between 4.19 and 5.2.
|
||||
|
||||
From: Dmitry Osipenko <digetx@gmail.com>
|
||||
|
||||
The rotation mode from cmdline shouldn't be taken into account if it
|
||||
wasn't specified in the cmdline. This fixes ignored default display
|
||||
orientation when display mode is given using cmdline without the
|
||||
rotation being specified.
|
||||
|
||||
Fixes: 1bf4e09227c3 ("drm/modes: Allow to specify rotation and reflection on the commandline")
|
||||
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/drm_fb_helper.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
|
||||
index cfa272fab56a..a0b217f93a0d 100644
|
||||
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||||
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||||
@@ -2497,7 +2497,7 @@ static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
|
||||
* simple XOR between the two handle the addition nicely.
|
||||
*/
|
||||
cmdline = &connector->cmdline_mode;
|
||||
- if (cmdline->specified) {
|
||||
+ if (cmdline->specified && cmdline->rotation_reflection) {
|
||||
unsigned int cmdline_rest, panel_rest;
|
||||
unsigned int cmdline_rot, panel_rot;
|
||||
unsigned int sum_rot, sum_rest;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,355 +0,0 @@
|
|||
From 5e484a3e2a1118e66ec39a007ac5a9f83fe20114 Mon Sep 17 00:00:00 2001
|
||||
From: Chen-Yu Tsai <wens@csie.org>
|
||||
Date: Thu, 18 Jul 2019 17:07:05 +0800
|
||||
Subject: [PATCH 754/826] staging: bcm2835-codec: switch to multi-planar API
|
||||
|
||||
There are two APIs for mem2mem devices, the older single-planar API and
|
||||
the newer multi-planar one. Without making things overly complex, the
|
||||
driver can only support one or the other. However the userspace libv4l2
|
||||
library has a plugin that allows multi-planar API devices to service
|
||||
single-planar consumers.
|
||||
|
||||
Chromium supports the multi-planar API exclusively, though this is
|
||||
currently limited to ChromiumOS. It would be possible to add support
|
||||
for generic Linux.
|
||||
|
||||
Switching to the multi-planar API would allow usage of both APIs from
|
||||
userspace.
|
||||
|
||||
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
.../bcm2835-codec/bcm2835-v4l2-codec.c | 145 +++++++++---------
|
||||
1 file changed, 76 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index 708f76b7aa92..43b903cd5391 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
|
||||
|
||||
for (k = 0; k < fmts->num_entries; k++) {
|
||||
fmt = &fmts->list[k];
|
||||
- if (fmt->fourcc == f->fmt.pix.pixelformat)
|
||||
+ if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
|
||||
break;
|
||||
}
|
||||
if (k == fmts->num_entries)
|
||||
@@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
|
||||
enum v4l2_buf_type type)
|
||||
{
|
||||
switch (type) {
|
||||
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
||||
return &ctx->q_data[V4L2_M2M_SRC];
|
||||
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
||||
return &ctx->q_data[V4L2_M2M_DST];
|
||||
default:
|
||||
v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
|
||||
@@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
|
||||
return NULL;
|
||||
|
||||
switch (type) {
|
||||
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
|
||||
return &ctx->component->input[0];
|
||||
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
|
||||
return &ctx->component->output[0];
|
||||
default:
|
||||
v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
|
||||
@@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
|
||||
format->es.video.crop.width, format->es.video.crop.height,
|
||||
format->es.video.color_space);
|
||||
|
||||
- q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
+ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
q_data->crop_width = format->es.video.crop.width;
|
||||
q_data->crop_height = format->es.video.crop.height;
|
||||
q_data->bytesperline = format->es.video.crop.width;
|
||||
@@ -945,7 +945,7 @@ static int vidioc_querycap(struct file *file, void *priv,
|
||||
strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
|
||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
|
||||
MEM2MEM_NAME);
|
||||
- cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
|
||||
+ cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
|
||||
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
|
||||
return 0;
|
||||
}
|
||||
@@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
|
||||
|
||||
q_data = get_q_data(ctx, f->type);
|
||||
|
||||
- f->fmt.pix.width = q_data->crop_width;
|
||||
- f->fmt.pix.height = q_data->height;
|
||||
- f->fmt.pix.field = V4L2_FIELD_NONE;
|
||||
- f->fmt.pix.pixelformat = q_data->fmt->fourcc;
|
||||
- f->fmt.pix.bytesperline = q_data->bytesperline;
|
||||
- f->fmt.pix.sizeimage = q_data->sizeimage;
|
||||
- f->fmt.pix.colorspace = ctx->colorspace;
|
||||
- f->fmt.pix.xfer_func = ctx->xfer_func;
|
||||
- f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
|
||||
- f->fmt.pix.quantization = ctx->quant;
|
||||
+ f->fmt.pix_mp.width = q_data->crop_width;
|
||||
+ f->fmt.pix_mp.height = q_data->height;
|
||||
+ f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc;
|
||||
+ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
|
||||
+ f->fmt.pix_mp.colorspace = ctx->colorspace;
|
||||
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage;
|
||||
+ f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
|
||||
+ f->fmt.pix_mp.num_planes = 1;
|
||||
+ f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
|
||||
+ f->fmt.pix_mp.quantization = ctx->quant;
|
||||
+ f->fmt.pix_mp.xfer_func = ctx->xfer_func;
|
||||
+
|
||||
+ memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
|
||||
+ sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
* The V4L2 specification requires the driver to correct the format
|
||||
* struct if any of the dimensions is unsupported
|
||||
*/
|
||||
- if (f->fmt.pix.width > MAX_W)
|
||||
- f->fmt.pix.width = MAX_W;
|
||||
- if (f->fmt.pix.height > MAX_H)
|
||||
- f->fmt.pix.height = MAX_H;
|
||||
+ if (f->fmt.pix_mp.width > MAX_W)
|
||||
+ f->fmt.pix_mp.width = MAX_W;
|
||||
+ if (f->fmt.pix_mp.height > MAX_H)
|
||||
+ f->fmt.pix_mp.height = MAX_H;
|
||||
|
||||
if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
|
||||
/* Only clip min w/h on capture. Treat 0x0 as unknown. */
|
||||
- if (f->fmt.pix.width < MIN_W)
|
||||
- f->fmt.pix.width = MIN_W;
|
||||
- if (f->fmt.pix.height < MIN_H)
|
||||
- f->fmt.pix.height = MIN_H;
|
||||
+ if (f->fmt.pix_mp.width < MIN_W)
|
||||
+ f->fmt.pix_mp.width = MIN_W;
|
||||
+ if (f->fmt.pix_mp.height < MIN_H)
|
||||
+ f->fmt.pix_mp.height = MIN_H;
|
||||
|
||||
/*
|
||||
* For codecs the buffer must have a vertical alignment of 16
|
||||
@@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
* some of the pixels are active.
|
||||
*/
|
||||
if (ctx->dev->role != ISP)
|
||||
- f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
|
||||
+ f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
|
||||
}
|
||||
- f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
|
||||
- fmt);
|
||||
- f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
|
||||
- f->fmt.pix.width,
|
||||
- f->fmt.pix.height,
|
||||
- fmt);
|
||||
+ f->fmt.pix_mp.num_planes = 1;
|
||||
+ f->fmt.pix_mp.plane_fmt[0].bytesperline =
|
||||
+ get_bytesperline(f->fmt.pix_mp.width, fmt);
|
||||
+ f->fmt.pix_mp.plane_fmt[0].sizeimage =
|
||||
+ get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
|
||||
+ f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt);
|
||||
+ memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
|
||||
+ sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
|
||||
|
||||
- f->fmt.pix.field = V4L2_FIELD_NONE;
|
||||
+ f->fmt.pix_mp.field = V4L2_FIELD_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
|
||||
fmt = find_format(f, ctx->dev, true);
|
||||
if (!fmt) {
|
||||
- f->fmt.pix.pixelformat = get_default_format(ctx->dev,
|
||||
- true)->fourcc;
|
||||
+ f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
|
||||
+ true)->fourcc;
|
||||
fmt = find_format(f, ctx->dev, true);
|
||||
}
|
||||
|
||||
@@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
|
||||
|
||||
fmt = find_format(f, ctx->dev, false);
|
||||
if (!fmt) {
|
||||
- f->fmt.pix.pixelformat = get_default_format(ctx->dev,
|
||||
- false)->fourcc;
|
||||
+ f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
|
||||
+ false)->fourcc;
|
||||
fmt = find_format(f, ctx->dev, false);
|
||||
}
|
||||
|
||||
- if (!f->fmt.pix.colorspace)
|
||||
- f->fmt.pix.colorspace = ctx->colorspace;
|
||||
+ if (!f->fmt.pix_mp.colorspace)
|
||||
+ f->fmt.pix_mp.colorspace = ctx->colorspace;
|
||||
|
||||
return vidioc_try_fmt(ctx, f, fmt);
|
||||
}
|
||||
@@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
bool update_capture_port = false;
|
||||
int ret;
|
||||
|
||||
- v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
|
||||
- f->type, f->fmt.pix.width, f->fmt.pix.height,
|
||||
- f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
|
||||
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
|
||||
+ f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
|
||||
+ f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
||||
+
|
||||
|
||||
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
|
||||
if (!vq)
|
||||
@@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
}
|
||||
|
||||
q_data->fmt = find_format(f, ctx->dev,
|
||||
- f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
- q_data->crop_width = f->fmt.pix.width;
|
||||
- q_data->height = f->fmt.pix.height;
|
||||
+ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
+ q_data->crop_width = f->fmt.pix_mp.width;
|
||||
+ q_data->height = f->fmt.pix_mp.height;
|
||||
if (!q_data->selection_set)
|
||||
q_data->crop_height = requested_height;
|
||||
|
||||
@@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
* Copying the behaviour of vicodec which retains a single set of
|
||||
* colorspace parameters for both input and output.
|
||||
*/
|
||||
- ctx->colorspace = f->fmt.pix.colorspace;
|
||||
- ctx->xfer_func = f->fmt.pix.xfer_func;
|
||||
- ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
|
||||
- ctx->quant = f->fmt.pix.quantization;
|
||||
+ ctx->colorspace = f->fmt.pix_mp.colorspace;
|
||||
+ ctx->xfer_func = f->fmt.pix_mp.xfer_func;
|
||||
+ ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
|
||||
+ ctx->quant = f->fmt.pix_mp.quantization;
|
||||
|
||||
/* All parameters should have been set correctly by try_fmt */
|
||||
- q_data->bytesperline = f->fmt.pix.bytesperline;
|
||||
- q_data->sizeimage = f->fmt.pix.sizeimage;
|
||||
+ q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
|
||||
+ q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
|
||||
|
||||
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
|
||||
q_data->bytesperline, q_data->sizeimage);
|
||||
|
||||
if (ctx->dev->role == DECODE &&
|
||||
q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
|
||||
- f->fmt.pix.width && f->fmt.pix.height) {
|
||||
+ q_data->crop_width && q_data->height) {
|
||||
/*
|
||||
* On the decoder, if provided with a resolution on the input
|
||||
* side, then replicate that to the output side.
|
||||
@@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
q_data_dst->height = ALIGN(q_data->crop_height, 16);
|
||||
|
||||
q_data_dst->bytesperline =
|
||||
- get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
|
||||
+ get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt);
|
||||
q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
|
||||
q_data_dst->crop_width,
|
||||
q_data_dst->height,
|
||||
@@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
- unsigned int height = f->fmt.pix.height;
|
||||
+ unsigned int height = f->fmt.pix_mp.height;
|
||||
int ret;
|
||||
|
||||
ret = vidioc_try_fmt_vid_cap(file, priv, f);
|
||||
@@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
- unsigned int height = f->fmt.pix.height;
|
||||
+ unsigned int height = f->fmt.pix_mp.height;
|
||||
int ret;
|
||||
|
||||
ret = vidioc_try_fmt_vid_out(file, priv, f);
|
||||
@@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct file *file, void *priv,
|
||||
{
|
||||
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||
struct bcm2835_codec_q_data *q_data;
|
||||
- bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
|
||||
+ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
|
||||
true : false;
|
||||
|
||||
if ((ctx->dev->role == DECODE && !capture_queue) ||
|
||||
@@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
||||
{
|
||||
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||
struct bcm2835_codec_q_data *q_data = NULL;
|
||||
- bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
|
||||
+ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
|
||||
true : false;
|
||||
|
||||
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
|
||||
@@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *file, void *priv,
|
||||
{
|
||||
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||
|
||||
- if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
|
||||
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||
return -EINVAL;
|
||||
|
||||
ctx->framerate_num =
|
||||
@@ -1738,15 +1745,15 @@ static int vidioc_encoder_cmd(struct file *file, void *priv,
|
||||
static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
|
||||
- .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
|
||||
- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
||||
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
|
||||
- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
|
||||
+ .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
|
||||
+ .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap,
|
||||
+ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
|
||||
+ .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
|
||||
|
||||
- .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
|
||||
- .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
|
||||
- .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
|
||||
- .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
|
||||
+ .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
|
||||
+ .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
|
||||
+ .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
|
||||
+ .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
|
||||
|
||||
.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
|
||||
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
|
||||
@@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming(struct vb2_queue *q,
|
||||
ctx->component_enabled = true;
|
||||
}
|
||||
|
||||
- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
|
||||
+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||
/*
|
||||
* Create the EOS buffer.
|
||||
* We only need the MMAL part, and want to NOT attach a memory
|
||||
@@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
|
||||
struct bcm2835_codec_ctx *ctx = priv;
|
||||
int ret;
|
||||
|
||||
- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
||||
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
|
||||
src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
|
||||
src_vq->drv_priv = ctx;
|
||||
src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
|
||||
@@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
|
||||
dst_vq->drv_priv = ctx;
|
||||
dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
From 962099a5bee23abfbf17815b21d94b3563ee18fe Mon Sep 17 00:00:00 2001
|
||||
From: Chen-Yu Tsai <wens@csie.org>
|
||||
Date: Mon, 22 Jul 2019 22:13:30 +0800
|
||||
Subject: [PATCH 755/826] staging: bcm2835-codec: implement
|
||||
V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
|
||||
|
||||
The stateful decoder specification shows an optional step for retrieving
|
||||
the miminum number of capture buffers required for the decoder to
|
||||
proceed. While not a required parameter, having it makes some
|
||||
applications happy.
|
||||
|
||||
bcm2835-codec is a little different from other decoder implementations
|
||||
in that there is an intermediate format conversion between the hardware
|
||||
and V4L2 buffers. The number of capture buffers required is therefore
|
||||
independent of the stream and DPB etc.
|
||||
|
||||
There are plans to remove the conversion, but it requires a fair amount
|
||||
of rework within the firmware. Until that is done, simply return a value
|
||||
of 1.
|
||||
|
||||
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
.../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index 43b903cd5391..a6a6e9d56d80 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -2357,6 +2357,18 @@ static int bcm2835_codec_open(struct file *file)
|
||||
}
|
||||
ctx->fh.ctrl_handler = hdl;
|
||||
v4l2_ctrl_handler_setup(hdl);
|
||||
+ } else if (dev->role == DECODE) {
|
||||
+ v4l2_ctrl_handler_init(hdl, 1);
|
||||
+
|
||||
+ v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
|
||||
+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
|
||||
+ 1, 1, 1, 1);
|
||||
+ if (hdl->error) {
|
||||
+ rc = hdl->error;
|
||||
+ goto free_ctrl_handler;
|
||||
+ }
|
||||
+ ctx->fh.ctrl_handler = hdl;
|
||||
+ v4l2_ctrl_handler_setup(hdl);
|
||||
}
|
||||
|
||||
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 8c54e77880234ee3937d0db7318c3e0dacfecb88 Mon Sep 17 00:00:00 2001
|
||||
From: Chen-Yu Tsai <wens@csie.org>
|
||||
Date: Mon, 22 Jul 2019 22:20:55 +0800
|
||||
Subject: [PATCH 756/826] staging: bcm2835-codec: set device_caps in struct
|
||||
video_device
|
||||
|
||||
Instead of filling in the struct v4l2_capability device_caps
|
||||
field, fill in the struct video_device device_caps field.
|
||||
|
||||
That way the V4L2 core knows what the capabilities of the
|
||||
video device are.
|
||||
|
||||
This is similar to a cleanup series by Hans Verkuil [1].
|
||||
|
||||
[1] https://www.spinics.net/lists/linux-media/msg153313.html
|
||||
|
||||
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
.../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index a6a6e9d56d80..2902e49a7c77 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -945,8 +945,6 @@ static int vidioc_querycap(struct file *file, void *priv,
|
||||
strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
|
||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
|
||||
MEM2MEM_NAME);
|
||||
- cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
|
||||
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2600,6 +2598,7 @@ static int bcm2835_codec_create(struct platform_device *pdev,
|
||||
vfd = &dev->vfd;
|
||||
vfd->lock = &dev->dev_mutex;
|
||||
vfd->v4l2_dev = &dev->v4l2_dev;
|
||||
+ vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
|
||||
|
||||
switch (role) {
|
||||
case DECODE:
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
From 41c722d8f45e1da8b8ffc8767162ac6483cbd18e Mon Sep 17 00:00:00 2001
|
||||
From: James Hughes <james.hughes@raspberrypi.org>
|
||||
Date: Tue, 16 Jul 2019 12:18:21 +0100
|
||||
Subject: [PATCH 757/826] Add HDMI1 facility to the driver.
|
||||
|
||||
For generic ALSA, all you need is the bcm2835.h change, but
|
||||
have also added structures for IEC958 HDMI. Not sure how to
|
||||
test those.
|
||||
---
|
||||
.../vc04_services/bcm2835-audio/bcm2835.c | 29 ++++++++++++++++---
|
||||
.../vc04_services/bcm2835-audio/bcm2835.h | 4 ++-
|
||||
2 files changed, 28 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
|
||||
index 86b921030db7..4d5b99d8ae9d 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
|
||||
@@ -79,7 +79,11 @@ static int bcm2835_audio_alsa_newpcm(struct bcm2835_chip *chip,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, 0, 1, true);
|
||||
+ err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, AUDIO_DEST_HDMI0, 1, true);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI1", 2, AUDIO_DEST_HDMI1, 1, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -106,7 +110,7 @@ static struct bcm2835_audio_driver bcm2835_audio_alsa = {
|
||||
.newctl = snd_bcm2835_new_ctl,
|
||||
};
|
||||
|
||||
-static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
|
||||
+static struct bcm2835_audio_driver bcm2835_audio_hdmi0 = {
|
||||
.driver = {
|
||||
.name = "bcm2835_hdmi",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -116,7 +120,20 @@ static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
|
||||
.minchannels = 1,
|
||||
.newpcm = bcm2835_audio_simple_newpcm,
|
||||
.newctl = snd_bcm2835_new_hdmi_ctl,
|
||||
- .route = AUDIO_DEST_HDMI
|
||||
+ .route = AUDIO_DEST_HDMI0
|
||||
+};
|
||||
+
|
||||
+static struct bcm2835_audio_driver bcm2835_audio_hdmi1 = {
|
||||
+ .driver = {
|
||||
+ .name = "bcm2835_hdmi",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+ .shortname = "bcm2835 HDMI 1",
|
||||
+ .longname = "bcm2835 HDMI 1",
|
||||
+ .minchannels = 1,
|
||||
+ .newpcm = bcm2835_audio_simple_newpcm,
|
||||
+ .newctl = snd_bcm2835_new_hdmi_ctl,
|
||||
+ .route = AUDIO_DEST_HDMI1
|
||||
};
|
||||
|
||||
static struct bcm2835_audio_driver bcm2835_audio_headphones = {
|
||||
@@ -143,7 +160,11 @@ static struct bcm2835_audio_drivers children_devices[] = {
|
||||
.is_enabled = &enable_compat_alsa,
|
||||
},
|
||||
{
|
||||
- .audio_driver = &bcm2835_audio_hdmi,
|
||||
+ .audio_driver = &bcm2835_audio_hdmi0,
|
||||
+ .is_enabled = &enable_hdmi,
|
||||
+ },
|
||||
+ {
|
||||
+ .audio_driver = &bcm2835_audio_hdmi1,
|
||||
.is_enabled = &enable_hdmi,
|
||||
},
|
||||
{
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
|
||||
index 595ad584243f..67beb9f17dc5 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
|
||||
@@ -33,7 +33,9 @@ enum {
|
||||
enum snd_bcm2835_route {
|
||||
AUDIO_DEST_AUTO = 0,
|
||||
AUDIO_DEST_HEADPHONES = 1,
|
||||
- AUDIO_DEST_HDMI = 2,
|
||||
+ AUDIO_DEST_HDMI = 2, // for backwards compatibility.
|
||||
+ AUDIO_DEST_HDMI0 = 2,
|
||||
+ AUDIO_DEST_HDMI1 = 3,
|
||||
AUDIO_DEST_MAX,
|
||||
};
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
From a08305b0a8318f07b1fe06825985373373f0fa65 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Mon, 5 Aug 2019 14:17:14 +0100
|
||||
Subject: [PATCH 758/826] overlays: Add baudrate parameter to i2c3-i2c6
|
||||
|
||||
The overlays for enabling the new BCM2711 I2C interfaces were lacking
|
||||
the means to configure the baud/clock rate.
|
||||
|
||||
Also explictly set the default pins, rather than relying on the values
|
||||
in the base DTB.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 8 ++++++++
|
||||
arch/arm/boot/dts/overlays/i2c3-overlay.dts | 15 ++++++++++++---
|
||||
arch/arm/boot/dts/overlays/i2c4-overlay.dts | 15 ++++++++++++---
|
||||
arch/arm/boot/dts/overlays/i2c5-overlay.dts | 15 ++++++++++++---
|
||||
arch/arm/boot/dts/overlays/i2c6-overlay.dts | 15 ++++++++++++---
|
||||
5 files changed, 56 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
|
||||
index 6131ac3d967c..a034d07be96a 100644
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -1221,6 +1221,8 @@ Info: Enable the i2c3 bus
|
||||
Load: dtoverlay=i2c3,<param>
|
||||
Params: pins_2_3 Use GPIOs 2 and 3
|
||||
pins_4_5 Use GPIOs 4 and 5 (default)
|
||||
+ baudrate Set the baudrate for the interface (default
|
||||
+ "100000")
|
||||
|
||||
|
||||
Name: i2c4
|
||||
@@ -1228,6 +1230,8 @@ Info: Enable the i2c4 bus
|
||||
Load: dtoverlay=i2c4,<param>
|
||||
Params: pins_6_7 Use GPIOs 6 and 7
|
||||
pins_8_9 Use GPIOs 8 and 9 (default)
|
||||
+ baudrate Set the baudrate for the interface (default
|
||||
+ "100000")
|
||||
|
||||
|
||||
Name: i2c5
|
||||
@@ -1235,6 +1239,8 @@ Info: Enable the i2c5 bus
|
||||
Load: dtoverlay=i2c5,<param>
|
||||
Params: pins_10_11 Use GPIOs 10 and 11
|
||||
pins_12_13 Use GPIOs 12 and 13 (default)
|
||||
+ baudrate Set the baudrate for the interface (default
|
||||
+ "100000")
|
||||
|
||||
|
||||
Name: i2c6
|
||||
@@ -1242,6 +1248,8 @@ Info: Enable the i2c6 bus
|
||||
Load: dtoverlay=i2c6,<param>
|
||||
Params: pins_0_1 Use GPIOs 0 and 1
|
||||
pins_22_23 Use GPIOs 22 and 23 (default)
|
||||
+ baudrate Set the baudrate for the interface (default
|
||||
+ "100000")
|
||||
|
||||
|
||||
Name: i2s-gpio28-31
|
||||
diff --git a/arch/arm/boot/dts/overlays/i2c3-overlay.dts b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
|
||||
index 79d0da0ca6f2..f651f3541d25 100644
|
||||
--- a/arch/arm/boot/dts/overlays/i2c3-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/i2c3-overlay.dts
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
fragment@0 {
|
||||
target = <&i2c3>;
|
||||
- __overlay__ {
|
||||
+ frag0: __overlay__ {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c3_pins>;
|
||||
+ clock-frequency = <100000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -20,8 +21,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ fragment@2 {
|
||||
+ target = <&i2c3_pins>;
|
||||
+ __overlay__ {
|
||||
+ brcm,pins = <4 5>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
- pins_2_3 = <0>,"=1";
|
||||
- pins_4_5 = <0>,"!1";
|
||||
+ pins_2_3 = <0>,"=1!2";
|
||||
+ pins_4_5 = <0>,"!1=2";
|
||||
+ baudrate = <&frag0>, "clock-frequency:0";
|
||||
};
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/overlays/i2c4-overlay.dts b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
|
||||
index ffad91763f07..3cfd87913918 100644
|
||||
--- a/arch/arm/boot/dts/overlays/i2c4-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/i2c4-overlay.dts
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
fragment@0 {
|
||||
target = <&i2c4>;
|
||||
- __overlay__ {
|
||||
+ frag0: __overlay__ {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c4_pins>;
|
||||
+ clock-frequency = <100000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -20,8 +21,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ fragment@2 {
|
||||
+ target = <&i2c4_pins>;
|
||||
+ __overlay__ {
|
||||
+ brcm,pins = <8 9>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
- pins_6_7 = <0>,"=1";
|
||||
- pins_8_9 = <0>,"!1";
|
||||
+ pins_6_7 = <0>,"=1!2";
|
||||
+ pins_8_9 = <0>,"!1=2";
|
||||
+ baudrate = <&frag0>, "clock-frequency:0";
|
||||
};
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/overlays/i2c5-overlay.dts b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
|
||||
index 551ce154f877..c71f511d90cf 100644
|
||||
--- a/arch/arm/boot/dts/overlays/i2c5-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/i2c5-overlay.dts
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
fragment@0 {
|
||||
target = <&i2c5>;
|
||||
- __overlay__ {
|
||||
+ frag0: __overlay__ {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c5_pins>;
|
||||
+ clock-frequency = <100000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -20,8 +21,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ fragment@2 {
|
||||
+ target = <&i2c5_pins>;
|
||||
+ __overlay__ {
|
||||
+ brcm,pins = <12 13>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
- pins_10_11 = <0>,"=1";
|
||||
- pins_12_13 = <0>,"!1";
|
||||
+ pins_10_11 = <0>,"=1!2";
|
||||
+ pins_12_13 = <0>,"!1=2";
|
||||
+ baudrate = <&frag0>, "clock-frequency:0";
|
||||
};
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/overlays/i2c6-overlay.dts b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
|
||||
index 0a67f7da6ac0..17861ef00c5b 100644
|
||||
--- a/arch/arm/boot/dts/overlays/i2c6-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/i2c6-overlay.dts
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
fragment@0 {
|
||||
target = <&i2c6>;
|
||||
- __overlay__ {
|
||||
+ frag0: __overlay__ {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c6_pins>;
|
||||
+ clock-frequency = <100000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -20,8 +21,16 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ fragment@2 {
|
||||
+ target = <&i2c6_pins>;
|
||||
+ __overlay__ {
|
||||
+ brcm,pins = <22 23>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
- pins_0_1 = <0>,"=1";
|
||||
- pins_22_23 = <0>,"!1";
|
||||
+ pins_0_1 = <0>,"=1!2";
|
||||
+ pins_22_23 = <0>,"!1=2";
|
||||
+ baudrate = <&frag0>, "clock-frequency:0";
|
||||
};
|
||||
};
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
From a5b534bb890687b7fc08787ad47421e8f6d72422 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Thu, 25 Jul 2019 17:27:44 +0100
|
||||
Subject: [PATCH 760/826] drm/vc4: Resolve the vblank warnings on mode
|
||||
switching
|
||||
|
||||
The details over when and how a driver is to service the
|
||||
vblank events are sketchy, and the fkms driver was triggering
|
||||
a kernel warning every time the crtc was enabled or disabled.
|
||||
|
||||
Copy the event handling as used by the vc4-kms driver slightly
|
||||
more closely, and we avoid the warnings.
|
||||
|
||||
https://github.com/raspberrypi/linux/issues/3020
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++--------
|
||||
1 file changed, 33 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
index 066f6d17db97..425625b24e29 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
@@ -933,6 +933,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
|
||||
static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
|
||||
{
|
||||
+ struct drm_device *dev = crtc->dev;
|
||||
struct drm_plane *plane;
|
||||
|
||||
DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
|
||||
@@ -948,6 +949,35 @@ static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_s
|
||||
|
||||
drm_atomic_crtc_for_each_plane(plane, crtc)
|
||||
vc4_plane_atomic_disable(plane, plane->state);
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure we issue a vblank event after disabling the CRTC if
|
||||
+ * someone was waiting it.
|
||||
+ */
|
||||
+ if (crtc->state->event) {
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&dev->event_lock, flags);
|
||||
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
||||
+ crtc->state->event = NULL;
|
||||
+ spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void vc4_crtc_consume_event(struct drm_crtc *crtc)
|
||||
+{
|
||||
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
|
||||
+ struct drm_device *dev = crtc->dev;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ crtc->state->event->pipe = drm_crtc_index(crtc);
|
||||
+
|
||||
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
+
|
||||
+ spin_lock_irqsave(&dev->event_lock, flags);
|
||||
+ vc4_crtc->event = crtc->state->event;
|
||||
+ crtc->state->event = NULL;
|
||||
+ spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
}
|
||||
|
||||
static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
|
||||
@@ -957,6 +987,7 @@ static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_st
|
||||
DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
|
||||
crtc->base.id);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
+ vc4_crtc_consume_event(crtc);
|
||||
|
||||
/* Unblank the planes (if they're supposed to be displayed). */
|
||||
drm_atomic_crtc_for_each_plane(plane, crtc)
|
||||
@@ -1028,23 +1059,10 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
{
|
||||
- struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
|
||||
- struct drm_device *dev = crtc->dev;
|
||||
-
|
||||
DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
|
||||
crtc->base.id);
|
||||
- if (crtc->state->event) {
|
||||
- unsigned long flags;
|
||||
-
|
||||
- crtc->state->event->pipe = drm_crtc_index(crtc);
|
||||
-
|
||||
- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
-
|
||||
- spin_lock_irqsave(&dev->event_lock, flags);
|
||||
- vc4_crtc->event = crtc->state->event;
|
||||
- crtc->state->event = NULL;
|
||||
- spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
- }
|
||||
+ if (crtc->state->active && old_state->active && crtc->state->event)
|
||||
+ vc4_crtc_consume_event(crtc);
|
||||
}
|
||||
|
||||
static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From c76cadf3388c4fb96cd57139dae6f4581ee13f77 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Thu, 25 Jul 2019 17:34:29 +0100
|
||||
Subject: [PATCH 761/826] drm/vc4: Remove unused mode variable
|
||||
|
||||
"89d1376 drm/vc4: Add support for margins to fkms" removed
|
||||
the requirement for having the mode structure from vc4_plane_to_mb,
|
||||
but didn't remove it as a local to the function, causing a
|
||||
compiler warning.
|
||||
|
||||
Remove the unused variable.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
index 425625b24e29..357b497f19ae 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
@@ -523,7 +523,6 @@ static int vc4_plane_to_mb(struct drm_plane *plane,
|
||||
const struct vc_image_format *vc_fmt =
|
||||
vc4_get_vc_image_fmt(drm_fmt->format);
|
||||
int num_planes = fb->format->num_planes;
|
||||
- struct drm_display_mode *mode = &state->crtc->mode;
|
||||
unsigned int rotation = SUPPORTED_ROTATIONS;
|
||||
|
||||
mb->plane.vc_image_type = vc_fmt->vc_image;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
From a86716fb9f7668aea882d1f890ff30b75eff4bfc Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Thu, 11 Jul 2019 14:57:09 +0100
|
||||
Subject: [PATCH 763/826] staging:bcm2835-codec: Expand logging on format
|
||||
setting
|
||||
|
||||
Adds some more useful logging during format changed events and
|
||||
s_fmt.
|
||||
|
||||
Reported by: zillevdr <zillevdr@gmx.de>
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
.../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index 2902e49a7c77..a6ef88958b60 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -753,6 +753,10 @@ static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
|
||||
format->es.video.color_space);
|
||||
|
||||
q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format was %ux%u, crop %ux%u\n",
|
||||
+ __func__, q_data->bytesperline, q_data->height,
|
||||
+ q_data->crop_width, q_data->crop_height);
|
||||
+
|
||||
q_data->crop_width = format->es.video.crop.width;
|
||||
q_data->crop_height = format->es.video.crop.height;
|
||||
q_data->bytesperline = format->es.video.crop.width;
|
||||
@@ -1110,10 +1114,10 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
||||
bool update_capture_port = false;
|
||||
int ret;
|
||||
|
||||
- v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
|
||||
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: " V4L2_FOURCC_CONV ", size %u\n",
|
||||
f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
|
||||
- f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
||||
-
|
||||
+ V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat),
|
||||
+ f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
||||
|
||||
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
|
||||
if (!vq)
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
From 6da0550a342143e11ca1d558b5307aac6c284514 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Thu, 11 Jul 2019 14:58:35 +0100
|
||||
Subject: [PATCH 764/826] staging: bcm2835-codec: Correct bytesperline on
|
||||
format changed
|
||||
|
||||
The handling of format changed events incorrectly set bytesperline
|
||||
to the cropped width, which ignored padding and formats with
|
||||
more than 8bpp.
|
||||
Fix these.
|
||||
|
||||
Reported by: zillevdr <zillevdr@gmx.de>
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
.../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
index a6ef88958b60..66edec1197ea 100644
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -759,7 +759,9 @@ static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
|
||||
|
||||
q_data->crop_width = format->es.video.crop.width;
|
||||
q_data->crop_height = format->es.video.crop.height;
|
||||
- q_data->bytesperline = format->es.video.crop.width;
|
||||
+ q_data->bytesperline = get_bytesperline(format->es.video.width,
|
||||
+ q_data->fmt);
|
||||
+
|
||||
q_data->height = format->es.video.height;
|
||||
q_data->sizeimage = format->buffer_size_min;
|
||||
if (format->es.video.color_space)
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From 76b2727efaca513fe81b4ba56658ea2b9f9d0907 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
Date: Wed, 7 Aug 2019 11:31:08 +0100
|
||||
Subject: [PATCH 765/826] drm/vc4: Add missing NULL check to
|
||||
vc4_crtc_consume_event
|
||||
|
||||
vc4_crtc_consume_event wasn't checking crtc->state->event was
|
||||
set before dereferencing it, leading to an OOPS.
|
||||
|
||||
Fixes "a5b534b drm/vc4: Resolve the vblank warnings on mode switching"
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
index 357b497f19ae..89ad71cff2bd 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
||||
@@ -969,6 +969,9 @@ static void vc4_crtc_consume_event(struct drm_crtc *crtc)
|
||||
struct drm_device *dev = crtc->dev;
|
||||
unsigned long flags;
|
||||
|
||||
+ if (!crtc->state->event)
|
||||
+ return;
|
||||
+
|
||||
crtc->state->event->pipe = drm_crtc_index(crtc);
|
||||
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From 02f18a908b8de64ffb2f18cc8acfd8892bc8b038 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Fri, 9 Aug 2019 08:51:43 +0100
|
||||
Subject: [PATCH 767/826] net: bcmgenet: Workaround #2 for Pi4 Ethernet fail
|
||||
|
||||
Some combinations of Pi 4Bs and Ethernet switches don't reliably get a
|
||||
DCHP-assigned IP address, leaving the unit with a self=assigned 169.254
|
||||
address. In the failure case, the Pi is left able to receive packets
|
||||
but not send them, suggesting that the MAC<->PHY link is getting into
|
||||
a bad state.
|
||||
|
||||
It has been found empirically that skipping a reset step by the genet
|
||||
driver prevents the failures. No downsides have been discovered yet,
|
||||
and unlike the forced renegotiation it doesn't increase the time to
|
||||
get an IP address, so the workaround is enabled by default; add
|
||||
|
||||
genet.skip_umac_reset=n
|
||||
|
||||
to the command line to disable it.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/3108
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||
index b02f33a2ff08..251166dfb8a8 100644
|
||||
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||
@@ -72,6 +72,10 @@
|
||||
#define GENET_RDMA_REG_OFF (priv->hw_params->rdma_offset + \
|
||||
TOTAL_DESC * DMA_DESC_SIZE)
|
||||
|
||||
+static bool skip_umac_reset = true;
|
||||
+module_param(skip_umac_reset, bool, 0444);
|
||||
+MODULE_PARM_DESC(skip_umac_reset, "Skip UMAC reset step");
|
||||
+
|
||||
static inline void bcmgenet_writel(u32 value, void __iomem *offset)
|
||||
{
|
||||
/* MIPS chips strapped for BE will automagically configure the
|
||||
@@ -1993,6 +1997,11 @@ static void reset_umac(struct bcmgenet_priv *priv)
|
||||
bcmgenet_rbuf_ctrl_set(priv, 0);
|
||||
udelay(10);
|
||||
|
||||
+ if (skip_umac_reset) {
|
||||
+ pr_warn("Skipping UMAC reset\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* disable MAC while updating its registers */
|
||||
bcmgenet_umac_writel(priv, 0, UMAC_CMD);
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From 167347104c80c4a61e0eff9de19682f5342477e1 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Anholt <eric@anholt.net>
|
||||
Date: Fri, 3 Aug 2018 11:22:27 +0200
|
||||
Subject: [PATCH 814/826] drm/vc4: Fix TILE_Y_OFFSET definitions
|
||||
|
||||
Y_OFFSET field starts at bit 8 not 7.
|
||||
|
||||
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-1-boris.brezillon@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_regs.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
|
||||
index d6864fa4bd14..ccbd6b377ffe 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_regs.h
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
|
||||
@@ -1043,8 +1043,8 @@ enum hvs_pixel_format {
|
||||
#define SCALER_PITCH0_TILE_LINE_DIR BIT(15)
|
||||
#define SCALER_PITCH0_TILE_INITIAL_LINE_DIR BIT(14)
|
||||
/* Y offset within a tile. */
|
||||
-#define SCALER_PITCH0_TILE_Y_OFFSET_MASK VC4_MASK(13, 7)
|
||||
-#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT 7
|
||||
+#define SCALER_PITCH0_TILE_Y_OFFSET_MASK VC4_MASK(13, 8)
|
||||
+#define SCALER_PITCH0_TILE_Y_OFFSET_SHIFT 8
|
||||
#define SCALER_PITCH0_TILE_WIDTH_R_MASK VC4_MASK(6, 0)
|
||||
#define SCALER_PITCH0_TILE_WIDTH_R_SHIFT 0
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From 904a5b062a6fb566da579b5ccc4c11ee93d825e3 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Anholt <eric@anholt.net>
|
||||
Date: Fri, 3 Aug 2018 11:22:28 +0200
|
||||
Subject: [PATCH 815/826] drm/vc4: Define missing PITCH0_SINK_PIX field
|
||||
|
||||
This is needed to support X/Y negative placement of planes using
|
||||
T-format buffers.
|
||||
|
||||
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-2-boris.brezillon@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_regs.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
|
||||
index ccbd6b377ffe..931088014272 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_regs.h
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
|
||||
@@ -1037,6 +1037,10 @@ enum hvs_pixel_format {
|
||||
#define SCALER_TILE_HEIGHT_MASK VC4_MASK(15, 0)
|
||||
#define SCALER_TILE_HEIGHT_SHIFT 0
|
||||
|
||||
+/* Common PITCH0 fields */
|
||||
+#define SCALER_PITCH0_SINK_PIX_MASK VC4_MASK(31, 26)
|
||||
+#define SCALER_PITCH0_SINK_PIX_SHIFT 26
|
||||
+
|
||||
/* PITCH0 fields for T-tiled. */
|
||||
#define SCALER_PITCH0_TILE_WIDTH_L_MASK VC4_MASK(22, 16)
|
||||
#define SCALER_PITCH0_TILE_WIDTH_L_SHIFT 16
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
From 299176a3472b3dcec51a29cf561f7fee804d0614 Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Date: Fri, 3 Aug 2018 11:22:29 +0200
|
||||
Subject: [PATCH 816/826] drm/vc4: Use drm_atomic_helper_check_plane_state() to
|
||||
simplify the logic
|
||||
|
||||
drm_atomic_helper_check_plane_state() takes care of checking the
|
||||
scaling capabilities and calculating the clipped X/Y offsets for us.
|
||||
|
||||
Rely on this function instead of open-coding the logic.
|
||||
|
||||
Incidentally, it seems to fix a problem we had with negative X/Y
|
||||
positioning of YUV planes.
|
||||
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Reviewed-by: Eric Anholt <eric@anholt.net>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-3-boris.brezillon@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_plane.c | 103 ++++++++++++++++----------------
|
||||
1 file changed, 52 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
index 3c3d97dbbb51..09186d69753b 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
@@ -313,31 +313,59 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
|
||||
u32 subpixel_src_mask = (1 << 16) - 1;
|
||||
u32 format = fb->format->format;
|
||||
int num_planes = fb->format->num_planes;
|
||||
- u32 h_subsample = 1;
|
||||
- u32 v_subsample = 1;
|
||||
- int ret;
|
||||
- int i;
|
||||
+ int min_scale = 1, max_scale = INT_MAX;
|
||||
+ struct drm_crtc_state *crtc_state;
|
||||
+ u32 h_subsample, v_subsample;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ crtc_state = drm_atomic_get_existing_crtc_state(state->state,
|
||||
+ state->crtc);
|
||||
+ if (!crtc_state) {
|
||||
+ DRM_DEBUG_KMS("Invalid crtc state\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* No configuring scaling on the cursor plane, since it gets
|
||||
+ * non-vblank-synced updates, and scaling requires LBM changes which
|
||||
+ * have to be vblank-synced.
|
||||
+ */
|
||||
+ if (plane->type == DRM_PLANE_TYPE_CURSOR) {
|
||||
+ min_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
+ max_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
+ } else {
|
||||
+ min_scale = 1;
|
||||
+ max_scale = INT_MAX;
|
||||
+ }
|
||||
+
|
||||
+ ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
+ min_scale, max_scale,
|
||||
+ true, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ h_subsample = drm_format_horz_chroma_subsampling(format);
|
||||
+ v_subsample = drm_format_vert_chroma_subsampling(format);
|
||||
|
||||
for (i = 0; i < num_planes; i++)
|
||||
vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
|
||||
|
||||
/* We don't support subpixel source positioning for scaling. */
|
||||
- if ((state->src_x & subpixel_src_mask) ||
|
||||
- (state->src_y & subpixel_src_mask) ||
|
||||
- (state->src_w & subpixel_src_mask) ||
|
||||
- (state->src_h & subpixel_src_mask)) {
|
||||
+ if ((state->src.x1 & subpixel_src_mask) ||
|
||||
+ (state->src.x2 & subpixel_src_mask) ||
|
||||
+ (state->src.y1 & subpixel_src_mask) ||
|
||||
+ (state->src.y2 & subpixel_src_mask)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- vc4_state->src_x = state->src_x >> 16;
|
||||
- vc4_state->src_y = state->src_y >> 16;
|
||||
- vc4_state->src_w[0] = state->src_w >> 16;
|
||||
- vc4_state->src_h[0] = state->src_h >> 16;
|
||||
+ vc4_state->src_x = state->src.x1 >> 16;
|
||||
+ vc4_state->src_y = state->src.y1 >> 16;
|
||||
+ vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16;
|
||||
+ vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16;
|
||||
|
||||
- vc4_state->crtc_x = state->crtc_x;
|
||||
- vc4_state->crtc_y = state->crtc_y;
|
||||
- vc4_state->crtc_w = state->crtc_w;
|
||||
- vc4_state->crtc_h = state->crtc_h;
|
||||
+ vc4_state->crtc_x = state->dst.x1;
|
||||
+ vc4_state->crtc_y = state->dst.y1;
|
||||
+ vc4_state->crtc_w = state->dst.x2 - state->dst.x1;
|
||||
+ vc4_state->crtc_h = state->dst.y2 - state->dst.y1;
|
||||
|
||||
ret = vc4_plane_margins_adj(state);
|
||||
if (ret)
|
||||
@@ -354,8 +382,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
|
||||
if (num_planes > 1) {
|
||||
vc4_state->is_yuv = true;
|
||||
|
||||
- h_subsample = drm_format_horz_chroma_subsampling(format);
|
||||
- v_subsample = drm_format_vert_chroma_subsampling(format);
|
||||
vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
|
||||
vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
|
||||
|
||||
@@ -380,39 +406,14 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
|
||||
vc4_state->y_scaling[1] = VC4_SCALING_NONE;
|
||||
}
|
||||
|
||||
- /* No configuring scaling on the cursor plane, since it gets
|
||||
- non-vblank-synced updates, and scaling requires requires
|
||||
- LBM changes which have to be vblank-synced.
|
||||
- */
|
||||
- if (plane->type == DRM_PLANE_TYPE_CURSOR && !vc4_state->is_unity)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- /* Clamp the on-screen start x/y to 0. The hardware doesn't
|
||||
- * support negative y, and negative x wastes bandwidth.
|
||||
- */
|
||||
- if (vc4_state->crtc_x < 0) {
|
||||
- for (i = 0; i < num_planes; i++) {
|
||||
- u32 cpp = fb->format->cpp[i];
|
||||
- u32 subs = ((i == 0) ? 1 : h_subsample);
|
||||
-
|
||||
- vc4_state->offsets[i] += (cpp *
|
||||
- (-vc4_state->crtc_x) / subs);
|
||||
- }
|
||||
- vc4_state->src_w[0] += vc4_state->crtc_x;
|
||||
- vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
|
||||
- vc4_state->crtc_x = 0;
|
||||
- }
|
||||
-
|
||||
- if (vc4_state->crtc_y < 0) {
|
||||
- for (i = 0; i < num_planes; i++) {
|
||||
- u32 subs = ((i == 0) ? 1 : v_subsample);
|
||||
-
|
||||
- vc4_state->offsets[i] += (fb->pitches[i] *
|
||||
- (-vc4_state->crtc_y) / subs);
|
||||
- }
|
||||
- vc4_state->src_h[0] += vc4_state->crtc_y;
|
||||
- vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
|
||||
- vc4_state->crtc_y = 0;
|
||||
+ /* Adjust the base pointer to the first pixel to be scanned out. */
|
||||
+ for (i = 0; i < num_planes; i++) {
|
||||
+ vc4_state->offsets[i] += (vc4_state->src_y /
|
||||
+ (i ? v_subsample : 1)) *
|
||||
+ fb->pitches[i];
|
||||
+ vc4_state->offsets[i] += (vc4_state->src_x /
|
||||
+ (i ? h_subsample : 1)) *
|
||||
+ fb->format->cpp[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
From ed9e15008174c71274bda7bfd6168ba8b6b0f5f8 Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Date: Fri, 3 Aug 2018 11:22:30 +0200
|
||||
Subject: [PATCH 817/826] drm/vc4: Move ->offsets[] adjustment out of
|
||||
setup_clipping_and_scaling()
|
||||
|
||||
The offset adjustment depends on the framebuffer modified, so let's
|
||||
just move this operation in the DRM_FORMAT_MOD_LINEAR case inside
|
||||
vc4_plane_mode_set().
|
||||
|
||||
This we'll be able to fix offset calculation for
|
||||
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED and DRM_FORMAT_MOD_BROADCOM_SANDXXX.
|
||||
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Reviewed-by: Eric Anholt <eric@anholt.net>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-4-boris.brezillon@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_plane.c | 26 ++++++++++++++++----------
|
||||
1 file changed, 16 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
index 09186d69753b..42e96641f1ac 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
@@ -406,16 +406,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
|
||||
vc4_state->y_scaling[1] = VC4_SCALING_NONE;
|
||||
}
|
||||
|
||||
- /* Adjust the base pointer to the first pixel to be scanned out. */
|
||||
- for (i = 0; i < num_planes; i++) {
|
||||
- vc4_state->offsets[i] += (vc4_state->src_y /
|
||||
- (i ? v_subsample : 1)) *
|
||||
- fb->pitches[i];
|
||||
- vc4_state->offsets[i] += (vc4_state->src_x /
|
||||
- (i ? h_subsample : 1)) *
|
||||
- fb->format->cpp[i];
|
||||
- }
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -523,6 +513,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
||||
const struct hvs_format *format = vc4_get_hvs_format(fb->format->format);
|
||||
u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier);
|
||||
int num_planes = drm_format_num_planes(format->drm);
|
||||
+ u32 h_subsample, v_subsample;
|
||||
bool mix_plane_alpha;
|
||||
bool covers_screen;
|
||||
u32 scl0, scl1, pitch0;
|
||||
@@ -568,10 +559,25 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
||||
scl1 = vc4_get_scl_field(state, 0);
|
||||
}
|
||||
|
||||
+ h_subsample = drm_format_horz_chroma_subsampling(format->drm);
|
||||
+ v_subsample = drm_format_vert_chroma_subsampling(format->drm);
|
||||
+
|
||||
switch (base_format_mod) {
|
||||
case DRM_FORMAT_MOD_LINEAR:
|
||||
tiling = SCALER_CTL0_TILING_LINEAR;
|
||||
pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
|
||||
+
|
||||
+ /* Adjust the base pointer to the first pixel to be scanned
|
||||
+ * out.
|
||||
+ */
|
||||
+ for (i = 0; i < num_planes; i++) {
|
||||
+ vc4_state->offsets[i] += vc4_state->src_y /
|
||||
+ (i ? v_subsample : 1) *
|
||||
+ fb->pitches[i];
|
||||
+ vc4_state->offsets[i] += vc4_state->src_x /
|
||||
+ (i ? h_subsample : 1) *
|
||||
+ fb->format->cpp[i];
|
||||
+ }
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
From c3f1afdbcfef63fa720f6143f1ee417d8d87d4e7 Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Date: Fri, 3 Aug 2018 11:22:31 +0200
|
||||
Subject: [PATCH 818/826] drm/vc4: Fix X/Y positioning of planes using T_TILES
|
||||
modifier
|
||||
|
||||
X/Y positioning of T-format buffers is quite tricky and the current
|
||||
implementation was failing to position a plane using this format
|
||||
correctly when the CRTC X, Y or both X and Y offsets were negative.
|
||||
It was also failing when the SRC X/Y offsets were != 0.
|
||||
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Reviewed-by: Eric Anholt <eric@anholt.net>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-5-boris.brezillon@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_plane.c | 50 ++++++++++++++++++++++++++++-----
|
||||
1 file changed, 43 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
index 42e96641f1ac..267f8125d86f 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
@@ -578,22 +578,58 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
||||
(i ? h_subsample : 1) *
|
||||
fb->format->cpp[i];
|
||||
}
|
||||
+
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
|
||||
- /* For T-tiled, the FB pitch is "how many bytes from
|
||||
- * one row to the next, such that pitch * tile_h ==
|
||||
- * tile_size * tiles_per_row."
|
||||
- */
|
||||
u32 tile_size_shift = 12; /* T tiles are 4kb */
|
||||
+ /* Whole-tile offsets, mostly for setting the pitch. */
|
||||
+ u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5;
|
||||
u32 tile_h_shift = 5; /* 16 and 32bpp are 32 pixels high */
|
||||
+ u32 tile_w_mask = (1 << tile_w_shift) - 1;
|
||||
+ /* The height mask on 32-bit-per-pixel tiles is 63, i.e. twice
|
||||
+ * the height (in pixels) of a 4k tile.
|
||||
+ */
|
||||
+ u32 tile_h_mask = (2 << tile_h_shift) - 1;
|
||||
+ /* For T-tiled, the FB pitch is "how many bytes from one row to
|
||||
+ * the next, such that
|
||||
+ *
|
||||
+ * pitch * tile_h == tile_size * tiles_per_row
|
||||
+ */
|
||||
u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
|
||||
+ u32 tiles_l = vc4_state->src_x >> tile_w_shift;
|
||||
+ u32 tiles_r = tiles_w - tiles_l;
|
||||
+ u32 tiles_t = vc4_state->src_y >> tile_h_shift;
|
||||
+ /* Intra-tile offsets, which modify the base address (the
|
||||
+ * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
|
||||
+ * base address).
|
||||
+ */
|
||||
+ u32 tile_y = (vc4_state->src_y >> 4) & 1;
|
||||
+ u32 subtile_y = (vc4_state->src_y >> 2) & 3;
|
||||
+ u32 utile_y = vc4_state->src_y & 3;
|
||||
+ u32 x_off = vc4_state->src_x & tile_w_mask;
|
||||
+ u32 y_off = vc4_state->src_y & tile_h_mask;
|
||||
|
||||
tiling = SCALER_CTL0_TILING_256B_OR_T;
|
||||
+ pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
|
||||
+ VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
|
||||
+ VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
|
||||
+ VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
|
||||
+ vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
|
||||
+ vc4_state->offsets[0] += subtile_y << 8;
|
||||
+ vc4_state->offsets[0] += utile_y << 4;
|
||||
+
|
||||
+ /* Rows of tiles alternate left-to-right and right-to-left. */
|
||||
+ if (tiles_t & 1) {
|
||||
+ pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
|
||||
+ vc4_state->offsets[0] += (tiles_w - tiles_l) <<
|
||||
+ tile_size_shift;
|
||||
+ vc4_state->offsets[0] -= (1 + !tile_y) << 10;
|
||||
+ } else {
|
||||
+ vc4_state->offsets[0] += tiles_l << tile_size_shift;
|
||||
+ vc4_state->offsets[0] += tile_y << 10;
|
||||
+ }
|
||||
|
||||
- pitch0 = (VC4_SET_FIELD(0, SCALER_PITCH0_TILE_Y_OFFSET) |
|
||||
- VC4_SET_FIELD(0, SCALER_PITCH0_TILE_WIDTH_L) |
|
||||
- VC4_SET_FIELD(tiles_w, SCALER_PITCH0_TILE_WIDTH_R));
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
From f1c1b67b26ed3cb789037d1c844d4105deaa3cfd Mon Sep 17 00:00:00 2001
|
||||
From: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Date: Thu, 15 Nov 2018 11:58:51 +0100
|
||||
Subject: [PATCH 819/826] drm/vc4: Fix NULL pointer dereference in the async
|
||||
update path
|
||||
|
||||
vc4_plane_atomic_async_update() calls vc4_plane_atomic_check()
|
||||
which in turn calls vc4_plane_setup_clipping_and_scaling(), and since
|
||||
commit 58a6a36fe8e0 ("drm/vc4: Use
|
||||
drm_atomic_helper_check_plane_state() to simplify the logic"), this
|
||||
function accesses plane_state->state which will be NULL when called
|
||||
from the async update path because we're passing the current plane
|
||||
state, and plane_state->state has been assigned to NULL in
|
||||
drm_atomic_helper_swap_state().
|
||||
|
||||
Pass the new state instead of the current one (the new state has
|
||||
->state set to a non-NULL value).
|
||||
|
||||
Fixes: 58a6a36fe8e0 ("drm/vc4: Use drm_atomic_helper_check_plane_state() to simplify the logic")
|
||||
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
|
||||
Reviewed-by: Eric Anholt <eric@anholt.net>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20181115105852.9844-1-boris.brezillon@bootlin.com
|
||||
---
|
||||
drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++++++++--
|
||||
1 file changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
index 267f8125d86f..ce2749d90dd0 100644
|
||||
--- a/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
|
||||
@@ -905,7 +905,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb)
|
||||
static void vc4_plane_atomic_async_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
- struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
|
||||
+ struct vc4_plane_state *vc4_state, *new_vc4_state;
|
||||
|
||||
if (plane->state->fb != state->fb) {
|
||||
vc4_plane_async_set_fb(plane, state->fb);
|
||||
@@ -927,7 +927,18 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
|
||||
plane->state->src_y = state->src_y;
|
||||
|
||||
/* Update the display list based on the new crtc_x/y. */
|
||||
- vc4_plane_atomic_check(plane, plane->state);
|
||||
+ vc4_plane_atomic_check(plane, state);
|
||||
+
|
||||
+ new_vc4_state = to_vc4_plane_state(state);
|
||||
+ vc4_state = to_vc4_plane_state(plane->state);
|
||||
+
|
||||
+ /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
|
||||
+ vc4_state->dlist[vc4_state->pos0_offset] =
|
||||
+ new_vc4_state->dlist[vc4_state->pos0_offset];
|
||||
+ vc4_state->dlist[vc4_state->pos2_offset] =
|
||||
+ new_vc4_state->dlist[vc4_state->pos2_offset];
|
||||
+ vc4_state->dlist[vc4_state->ptr0_offset] =
|
||||
+ new_vc4_state->dlist[vc4_state->ptr0_offset];
|
||||
|
||||
/* Note that we can't just call vc4_plane_write_dlist()
|
||||
* because that would smash the context data that the HVS is
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
From 1f8e54151926498bd1f462d758301669cb354fd0 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Mon, 12 Aug 2019 15:48:39 +0100
|
||||
Subject: [PATCH 822/826] ARM: dts: bcm2711-rpi-4-b: I2C aliases and pulls
|
||||
|
||||
The I2C interface nodes need aliases to give them fixed bus numbers,
|
||||
and setting the pulls on the GPIOs (particularly 9-13) increases the
|
||||
chances of the bus working with weak or absent external pulls.
|
||||
|
||||
See: https://www.raspberrypi.org/forums/posting.php?mode=reply&f=107&t=248439
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
|
||||
index 9b5c4f8a4d17..18c0f9599d3a 100644
|
||||
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
|
||||
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
|
||||
@@ -23,6 +23,10 @@
|
||||
mmc0 = &emmc2;
|
||||
mmc1 = &mmcnr;
|
||||
mmc2 = &sdhost;
|
||||
+ i2c3 = &i2c3;
|
||||
+ i2c4 = &i2c4;
|
||||
+ i2c5 = &i2c5;
|
||||
+ i2c6 = &i2c6;
|
||||
/delete-property/ ethernet;
|
||||
/delete-property/ intc;
|
||||
ethernet0 = &genet;
|
||||
@@ -207,31 +211,37 @@
|
||||
i2c0_pins: i2c0 {
|
||||
brcm,pins = <0 1>;
|
||||
brcm,function = <BCM2835_FSEL_ALT0>;
|
||||
+ brcm,pull = <BCM2835_PUD_UP>;
|
||||
};
|
||||
|
||||
i2c1_pins: i2c1 {
|
||||
brcm,pins = <2 3>;
|
||||
brcm,function = <BCM2835_FSEL_ALT0>;
|
||||
+ brcm,pull = <BCM2835_PUD_UP>;
|
||||
};
|
||||
|
||||
i2c3_pins: i2c3 {
|
||||
brcm,pins = <4 5>;
|
||||
brcm,function = <BCM2835_FSEL_ALT5>;
|
||||
+ brcm,pull = <BCM2835_PUD_UP>;
|
||||
};
|
||||
|
||||
i2c4_pins: i2c4 {
|
||||
brcm,pins = <8 9>;
|
||||
brcm,function = <BCM2835_FSEL_ALT5>;
|
||||
+ brcm,pull = <BCM2835_PUD_UP>;
|
||||
};
|
||||
|
||||
i2c5_pins: i2c5 {
|
||||
brcm,pins = <12 13>;
|
||||
brcm,function = <BCM2835_FSEL_ALT5>;
|
||||
+ brcm,pull = <BCM2835_PUD_UP>;
|
||||
};
|
||||
|
||||
i2c6_pins: i2c6 {
|
||||
brcm,pins = <22 23>;
|
||||
brcm,function = <BCM2835_FSEL_ALT5>;
|
||||
+ brcm,pull = <BCM2835_PUD_UP>;
|
||||
};
|
||||
|
||||
i2s_pins: i2s {
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
From 5f945aad8e7668a6f59b281c60aad87524a32a15 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
Date: Tue, 13 Aug 2019 15:53:29 +0100
|
||||
Subject: [PATCH 823/826] xhci: Use more event ring segment table entries
|
||||
|
||||
Users have reported log spam created by "Event Ring Full" xHC event
|
||||
TRBs. These are caused by interrupt latency in conjunction with a very
|
||||
busy set of devices on the bus. The errors are benign, but throughput
|
||||
will suffer as the xHC will pause processing of transfers until the
|
||||
event ring is drained by the kernel. Expand the number of event TRB slots
|
||||
available by increasing the number of event ring segments in the ERST.
|
||||
|
||||
Controllers have a hardware-defined limit as to the number of ERST
|
||||
entries they can process, so make the actual number in use
|
||||
min(ERST_MAX_SEGS, hw_max).
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
---
|
||||
drivers/usb/host/xhci-mem.c | 8 +++++---
|
||||
drivers/usb/host/xhci.h | 4 ++--
|
||||
2 files changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
||||
index b1f27aa38b10..7e417b71d24c 100644
|
||||
--- a/drivers/usb/host/xhci-mem.c
|
||||
+++ b/drivers/usb/host/xhci-mem.c
|
||||
@@ -2491,9 +2491,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
||||
* Event ring setup: Allocate a normal ring, but also setup
|
||||
* the event ring segment table (ERST). Section 4.9.3.
|
||||
*/
|
||||
+ val2 = 1 << HCS_ERST_MAX(xhci->hcs_params2);
|
||||
+ val2 = min_t(unsigned int, ERST_MAX_SEGS, val2);
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Allocating event ring");
|
||||
- xhci->event_ring = xhci_ring_alloc(xhci, ERST_NUM_SEGS, 1, TYPE_EVENT,
|
||||
- 0, flags);
|
||||
+ xhci->event_ring = xhci_ring_alloc(xhci, val2, 1, TYPE_EVENT,
|
||||
+ 0, flags);
|
||||
if (!xhci->event_ring)
|
||||
goto fail;
|
||||
if (xhci_check_trb_in_td_math(xhci) < 0)
|
||||
@@ -2506,7 +2508,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
||||
/* set ERST count with the number of entries in the segment table */
|
||||
val = readl(&xhci->ir_set->erst_size);
|
||||
val &= ERST_SIZE_MASK;
|
||||
- val |= ERST_NUM_SEGS;
|
||||
+ val |= val2;
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"// Write ERST size = %i to ir_set 0 (some bits preserved)",
|
||||
val);
|
||||
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
|
||||
index 3a6c451777e7..ec515c563a37 100644
|
||||
--- a/drivers/usb/host/xhci.h
|
||||
+++ b/drivers/usb/host/xhci.h
|
||||
@@ -1643,8 +1643,8 @@ struct urb_priv {
|
||||
* Each segment table entry is 4*32bits long. 1K seems like an ok size:
|
||||
* (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
|
||||
* meaning 64 ring segments.
|
||||
- * Initial allocated size of the ERST, in number of entries */
|
||||
-#define ERST_NUM_SEGS 1
|
||||
+ * Maximum number of segments in the ERST */
|
||||
+#define ERST_MAX_SEGS 8
|
||||
/* Initial allocated size of the ERST, in number of entries */
|
||||
#define ERST_SIZE 64
|
||||
/* Initial number of event segment rings allocated */
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
From c0e4ca17457d6669a263e86a88f0036875fc019e Mon Sep 17 00:00:00 2001
|
||||
From: P33M <2474547+P33M@users.noreply.github.com>
|
||||
Date: Wed, 14 Aug 2019 14:35:50 +0100
|
||||
Subject: [PATCH 824/826] dwc_otg: use align_buf for small IN control transfers
|
||||
(#3150)
|
||||
|
||||
The hardware will do a 4-byte write to memory on any IN packet received
|
||||
that is between 1 and 3 bytes long. This tramples memory in the uvcvideo
|
||||
driver, as it uses a sequence of 1- and 2-byte control transfers to
|
||||
query the min/max/range/step of each individual camera control and
|
||||
gives us buffers that are offsets into a struct.
|
||||
|
||||
Catch small control transfers in the data phase and use the align_buf
|
||||
to bounce the correct number of bytes into the URB's buffer.
|
||||
|
||||
In general, short packets on non-control endpoints should be OK as URBs
|
||||
should have enough buffer space for a wMaxPacket size transfer.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/3148
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
---
|
||||
drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||
index cdfb9a6b7c59..9f2cd510c301 100644
|
||||
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||
@@ -1182,6 +1182,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
|
||||
dwc_otg_qtd_t *qtd;
|
||||
dwc_otg_hcd_urb_t *urb;
|
||||
void* ptr = NULL;
|
||||
+ uint16_t wLength;
|
||||
uint32_t intr_enable;
|
||||
unsigned long flags;
|
||||
gintmsk_data_t gintmsk = { .d32 = 0, };
|
||||
@@ -1293,6 +1294,23 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
|
||||
break;
|
||||
case DWC_OTG_CONTROL_DATA:
|
||||
DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
|
||||
+ /*
|
||||
+ * Hardware bug: small IN packets with length < 4
|
||||
+ * cause a 4-byte write to memory. We can only catch
|
||||
+ * the case where we know a short packet is going to be
|
||||
+ * returned in a control transfer, as the length is
|
||||
+ * specified in the setup packet. This is only an issue
|
||||
+ * for drivers that insist on packing a device's various
|
||||
+ * properties into a struct and querying them one at a
|
||||
+ * time (uvcvideo).
|
||||
+ * Force the use of align_buf so that the subsequent
|
||||
+ * memcpy puts the right number of bytes in the URB's
|
||||
+ * buffer.
|
||||
+ */
|
||||
+ wLength = ((uint16_t *)urb->setup_packet)[3];
|
||||
+ if (hc->ep_is_in && wLength < 4)
|
||||
+ ptr = hc->xfer_buff;
|
||||
+
|
||||
hc->data_pid_start = qtd->data_toggle;
|
||||
break;
|
||||
case DWC_OTG_CONTROL_STATUS:
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,834 +0,0 @@
|
|||
From ea2c11a187c0e248343452846457b94715e04969 Mon Sep 17 00:00:00 2001
|
||||
From: yaroslavros <yaroslavros@gmail.com>
|
||||
Date: Wed, 14 Aug 2019 15:22:55 +0100
|
||||
Subject: [PATCH 825/826] Ported pcie-brcmstb bounce buffer implementation to
|
||||
ARM64. (#3144)
|
||||
|
||||
Ported pcie-brcmstb bounce buffer implementation to ARM64.
|
||||
This enables full 4G RAM usage on Raspberry Pi in 64-bit mode.
|
||||
|
||||
Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
|
||||
---
|
||||
arch/arm64/include/asm/dma-mapping.h | 21 +
|
||||
arch/arm64/mm/dma-mapping.c | 50 ++
|
||||
drivers/pci/controller/Makefile | 3 +
|
||||
drivers/pci/controller/pcie-brcmstb-bounce.h | 2 +-
|
||||
.../pci/controller/pcie-brcmstb-bounce64.c | 576 ++++++++++++++++++
|
||||
drivers/pci/controller/pcie-brcmstb.c | 30 +-
|
||||
6 files changed, 658 insertions(+), 24 deletions(-)
|
||||
create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce64.c
|
||||
|
||||
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
|
||||
index b7847eb8a7bb..9195e524cb08 100644
|
||||
--- a/arch/arm64/include/asm/dma-mapping.h
|
||||
+++ b/arch/arm64/include/asm/dma-mapping.h
|
||||
@@ -24,6 +24,27 @@
|
||||
#include <xen/xen.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
+extern void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
|
||||
+ gfp_t gfp, unsigned long attrs);
|
||||
+extern void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
|
||||
+ dma_addr_t handle, unsigned long attrs);
|
||||
+extern int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
|
||||
+ unsigned long attrs);
|
||||
+extern int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
|
||||
+ unsigned long attrs);
|
||||
+extern int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir, unsigned long attrs);
|
||||
+extern void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int,
|
||||
+ enum dma_data_direction dir, unsigned long attrs);
|
||||
+extern void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir);
|
||||
+extern void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir);
|
||||
+
|
||||
+
|
||||
+
|
||||
extern const struct dma_map_ops dummy_dma_ops;
|
||||
|
||||
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
|
||||
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
|
||||
index d3a5bb16f0b2..b1f6d4e1f464 100644
|
||||
--- a/arch/arm64/mm/dma-mapping.c
|
||||
+++ b/arch/arm64/mm/dma-mapping.c
|
||||
@@ -138,6 +138,12 @@ static void *__dma_alloc(struct device *dev, size_t size,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+void *arm64_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
|
||||
+ gfp_t gfp, unsigned long attrs)
|
||||
+{
|
||||
+ return __dma_alloc(dev, size, handle, gfp, attrs);
|
||||
+}
|
||||
+
|
||||
static void __dma_free(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle,
|
||||
unsigned long attrs)
|
||||
@@ -154,6 +160,12 @@ static void __dma_free(struct device *dev, size_t size,
|
||||
swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs);
|
||||
}
|
||||
|
||||
+void arm64_dma_free(struct device *dev, size_t size, void *cpu_addr,
|
||||
+ dma_addr_t handle, unsigned long attrs)
|
||||
+{
|
||||
+ __dma_free(dev, size, cpu_addr, handle, attrs);
|
||||
+}
|
||||
+
|
||||
static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction dir,
|
||||
@@ -197,6 +209,12 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int arm64_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir, unsigned long attrs)
|
||||
+{
|
||||
+ return __swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
|
||||
+}
|
||||
+
|
||||
static void __swiotlb_unmap_sg_attrs(struct device *dev,
|
||||
struct scatterlist *sgl, int nelems,
|
||||
enum dma_data_direction dir,
|
||||
@@ -213,6 +231,12 @@ static void __swiotlb_unmap_sg_attrs(struct device *dev,
|
||||
swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
|
||||
}
|
||||
|
||||
+void arm64_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir, unsigned long attrs)
|
||||
+{
|
||||
+ __swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
|
||||
+}
|
||||
+
|
||||
static void __swiotlb_sync_single_for_cpu(struct device *dev,
|
||||
dma_addr_t dev_addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
@@ -245,6 +269,12 @@ static void __swiotlb_sync_sg_for_cpu(struct device *dev,
|
||||
swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
|
||||
}
|
||||
|
||||
+void arm64_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ __swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
|
||||
+}
|
||||
+
|
||||
static void __swiotlb_sync_sg_for_device(struct device *dev,
|
||||
struct scatterlist *sgl, int nelems,
|
||||
enum dma_data_direction dir)
|
||||
@@ -259,6 +289,12 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
|
||||
sg->length, dir);
|
||||
}
|
||||
|
||||
+void arm64_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, int nelems,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ __swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
|
||||
+}
|
||||
+
|
||||
static int __swiotlb_mmap_pfn(struct vm_area_struct *vma,
|
||||
unsigned long pfn, size_t size)
|
||||
{
|
||||
@@ -294,6 +330,13 @@ static int __swiotlb_mmap(struct device *dev,
|
||||
return __swiotlb_mmap_pfn(vma, pfn, size);
|
||||
}
|
||||
|
||||
+int arm64_dma_mmap(struct device *dev, struct vm_area_struct *vma,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
|
||||
+ unsigned long attrs)
|
||||
+{
|
||||
+ return __swiotlb_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
|
||||
+}
|
||||
+
|
||||
static int __swiotlb_get_sgtable_page(struct sg_table *sgt,
|
||||
struct page *page, size_t size)
|
||||
{
|
||||
@@ -314,6 +357,13 @@ static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
|
||||
return __swiotlb_get_sgtable_page(sgt, page, size);
|
||||
}
|
||||
|
||||
+int arm64_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
|
||||
+ unsigned long attrs)
|
||||
+{
|
||||
+ return __swiotlb_get_sgtable(dev, sgt, cpu_addr, dma_addr, size, attrs);
|
||||
+}
|
||||
+
|
||||
static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
|
||||
{
|
||||
if (swiotlb)
|
||||
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
|
||||
index c40b7b982ea4..71be2a0a7e68 100644
|
||||
--- a/drivers/pci/controller/Makefile
|
||||
+++ b/drivers/pci/controller/Makefile
|
||||
@@ -32,6 +32,9 @@ obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
|
||||
ifdef CONFIG_ARM
|
||||
obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
|
||||
endif
|
||||
+ifdef CONFIG_ARM64
|
||||
+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce64.o
|
||||
+endif
|
||||
|
||||
obj-$(CONFIG_VMD) += vmd.o
|
||||
# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
|
||||
diff --git a/drivers/pci/controller/pcie-brcmstb-bounce.h b/drivers/pci/controller/pcie-brcmstb-bounce.h
|
||||
index 2fe20a14d035..7caa0781329b 100644
|
||||
--- a/drivers/pci/controller/pcie-brcmstb-bounce.h
|
||||
+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef _PCIE_BRCMSTB_BOUNCE_H
|
||||
#define _PCIE_BRCMSTB_BOUNCE_H
|
||||
|
||||
-#ifdef CONFIG_ARM
|
||||
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
|
||||
|
||||
int brcm_pcie_bounce_init(struct device *dev, unsigned long buffer_size,
|
||||
dma_addr_t threshold);
|
||||
diff --git a/drivers/pci/controller/pcie-brcmstb-bounce64.c b/drivers/pci/controller/pcie-brcmstb-bounce64.c
|
||||
new file mode 100644
|
||||
index 000000000000..d9f1a46fc331
|
||||
--- /dev/null
|
||||
+++ b/drivers/pci/controller/pcie-brcmstb-bounce64.c
|
||||
@@ -0,0 +1,576 @@
|
||||
+/*
|
||||
+ * This code started out as a version of arch/arm/common/dmabounce.c,
|
||||
+ * modified to cope with highmem pages. Now it has been changed heavily -
|
||||
+ * it now preallocates a large block (currently 4MB) and carves it up
|
||||
+ * sequentially in ring fashion, and DMA is used to copy the data - to the
|
||||
+ * point where very little of the original remains.
|
||||
+ *
|
||||
+ * Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
|
||||
+ *
|
||||
+ * Original version by Brad Parker (brad@heeltoe.com)
|
||||
+ * Re-written by Christopher Hoover <ch@murgatroid.com>
|
||||
+ * Made generic by Deepak Saxena <dsaxena@plexity.net>
|
||||
+ *
|
||||
+ * Copyright (C) 2002 Hewlett Packard Company.
|
||||
+ * Copyright (C) 2004 MontaVista Software, Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * version 2 as published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/page-flags.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/dma-direct.h>
|
||||
+#include <linux/dmapool.h>
|
||||
+#include <linux/list.h>
|
||||
+#include <linux/scatterlist.h>
|
||||
+#include <linux/bitmap.h>
|
||||
+#include <linux/swiotlb.h>
|
||||
+
|
||||
+#include <asm/cacheflush.h>
|
||||
+
|
||||
+#define STATS
|
||||
+
|
||||
+#ifdef STATS
|
||||
+#define DO_STATS(X) do { X ; } while (0)
|
||||
+#else
|
||||
+#define DO_STATS(X) do { } while (0)
|
||||
+#endif
|
||||
+
|
||||
+/* ************************************************** */
|
||||
+
|
||||
+struct safe_buffer {
|
||||
+ struct list_head node;
|
||||
+
|
||||
+ /* original request */
|
||||
+ size_t size;
|
||||
+ int direction;
|
||||
+
|
||||
+ struct dmabounce_pool *pool;
|
||||
+ void *safe;
|
||||
+ dma_addr_t unsafe_dma_addr;
|
||||
+ dma_addr_t safe_dma_addr;
|
||||
+};
|
||||
+
|
||||
+struct dmabounce_pool {
|
||||
+ unsigned long pages;
|
||||
+ void *virt_addr;
|
||||
+ dma_addr_t dma_addr;
|
||||
+ unsigned long *alloc_map;
|
||||
+ unsigned long alloc_pos;
|
||||
+ spinlock_t lock;
|
||||
+ struct device *dev;
|
||||
+ unsigned long num_pages;
|
||||
+#ifdef STATS
|
||||
+ size_t max_size;
|
||||
+ unsigned long num_bufs;
|
||||
+ unsigned long max_bufs;
|
||||
+ unsigned long max_pages;
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+struct dmabounce_device_info {
|
||||
+ struct device *dev;
|
||||
+ dma_addr_t threshold;
|
||||
+ struct list_head safe_buffers;
|
||||
+ struct dmabounce_pool pool;
|
||||
+ rwlock_t lock;
|
||||
+#ifdef STATS
|
||||
+ unsigned long map_count;
|
||||
+ unsigned long unmap_count;
|
||||
+ unsigned long sync_dev_count;
|
||||
+ unsigned long sync_cpu_count;
|
||||
+ unsigned long fail_count;
|
||||
+ int attr_res;
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct dmabounce_device_info *g_dmabounce_device_info;
|
||||
+
|
||||
+extern int bcm2838_dma40_memcpy_init(void);
|
||||
+extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
|
||||
+
|
||||
+#ifdef STATS
|
||||
+static ssize_t
|
||||
+bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
+{
|
||||
+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
|
||||
+ return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
|
||||
+ device_info->map_count,
|
||||
+ device_info->unmap_count,
|
||||
+ device_info->sync_dev_count,
|
||||
+ device_info->sync_cpu_count,
|
||||
+ device_info->fail_count,
|
||||
+ device_info->pool.max_size,
|
||||
+ device_info->pool.num_bufs,
|
||||
+ device_info->pool.max_bufs,
|
||||
+ device_info->pool.num_pages * PAGE_SIZE,
|
||||
+ device_info->pool.max_pages * PAGE_SIZE);
|
||||
+}
|
||||
+
|
||||
+static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
|
||||
+#endif
|
||||
+
|
||||
+static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
|
||||
+ unsigned long buffer_size)
|
||||
+{
|
||||
+ int ret = -ENOMEM;
|
||||
+ pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
|
||||
+ pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
|
||||
+ if (!pool->alloc_map)
|
||||
+ goto err_bitmap;
|
||||
+ pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
|
||||
+ &pool->dma_addr, GFP_KERNEL);
|
||||
+ if (!pool->virt_addr)
|
||||
+ goto err_dmabuf;
|
||||
+
|
||||
+ pool->alloc_pos = 0;
|
||||
+ spin_lock_init(&pool->lock);
|
||||
+ pool->dev = dev;
|
||||
+ pool->num_pages = 0;
|
||||
+
|
||||
+ DO_STATS(pool->max_size = 0);
|
||||
+ DO_STATS(pool->num_bufs = 0);
|
||||
+ DO_STATS(pool->max_bufs = 0);
|
||||
+ DO_STATS(pool->max_pages = 0);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_dmabuf:
|
||||
+ bitmap_free(pool->alloc_map);
|
||||
+err_bitmap:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void bounce_destroy(struct dmabounce_pool *pool)
|
||||
+{
|
||||
+ dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
|
||||
+ pool->dma_addr);
|
||||
+
|
||||
+ bitmap_free(pool->alloc_map);
|
||||
+}
|
||||
+
|
||||
+static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
|
||||
+ dma_addr_t *dmaaddrp)
|
||||
+{
|
||||
+ unsigned long pages;
|
||||
+ unsigned long flags;
|
||||
+ unsigned long pos;
|
||||
+
|
||||
+ pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
|
||||
+
|
||||
+ DO_STATS(pool->max_size = max(size, pool->max_size));
|
||||
+
|
||||
+ spin_lock_irqsave(&pool->lock, flags);
|
||||
+ pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
|
||||
+ pool->alloc_pos, pages, 0);
|
||||
+ /* If not found, try from the start */
|
||||
+ if (pos >= pool->pages && pool->alloc_pos)
|
||||
+ pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
|
||||
+ 0, pages, 0);
|
||||
+
|
||||
+ if (pos >= pool->pages) {
|
||||
+ spin_unlock_irqrestore(&pool->lock, flags);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ bitmap_set(pool->alloc_map, pos, pages);
|
||||
+ pool->alloc_pos = (pos + pages) % pool->pages;
|
||||
+ pool->num_pages += pages;
|
||||
+
|
||||
+ DO_STATS(pool->num_bufs++);
|
||||
+ DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
|
||||
+ DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
|
||||
+
|
||||
+ spin_unlock_irqrestore(&pool->lock, flags);
|
||||
+
|
||||
+ *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
|
||||
+
|
||||
+ return pool->virt_addr + pos * PAGE_SIZE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
|
||||
+{
|
||||
+ unsigned long pages;
|
||||
+ unsigned long flags;
|
||||
+ unsigned long pos;
|
||||
+
|
||||
+ pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
|
||||
+ pos = (buf - pool->virt_addr)/PAGE_SIZE;
|
||||
+
|
||||
+ BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
|
||||
+
|
||||
+ spin_lock_irqsave(&pool->lock, flags);
|
||||
+ bitmap_clear(pool->alloc_map, pos, pages);
|
||||
+ pool->num_pages -= pages;
|
||||
+ if (pool->num_pages == 0)
|
||||
+ pool->alloc_pos = 0;
|
||||
+ DO_STATS(pool->num_bufs--);
|
||||
+ spin_unlock_irqrestore(&pool->lock, flags);
|
||||
+}
|
||||
+
|
||||
+/* allocate a 'safe' buffer and keep track of it */
|
||||
+static struct safe_buffer *
|
||||
+alloc_safe_buffer(struct dmabounce_device_info *device_info,
|
||||
+ dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct safe_buffer *buf;
|
||||
+ struct dmabounce_pool *pool = &device_info->pool;
|
||||
+ struct device *dev = device_info->dev;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ /*
|
||||
+ * Although one might expect this to be called in thread context,
|
||||
+ * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
|
||||
+ * was previously used to select the appropriate allocation mode,
|
||||
+ * but this is unsafe.
|
||||
+ */
|
||||
+ buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
|
||||
+ if (!buf) {
|
||||
+ dev_warn(dev, "%s: kmalloc failed\n", __func__);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ buf->unsafe_dma_addr = dma_addr;
|
||||
+ buf->size = size;
|
||||
+ buf->direction = dir;
|
||||
+ buf->pool = pool;
|
||||
+
|
||||
+ buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
|
||||
+
|
||||
+ if (!buf->safe) {
|
||||
+ dev_warn(dev,
|
||||
+ "%s: could not alloc dma memory (size=%d)\n",
|
||||
+ __func__, size);
|
||||
+ kfree(buf);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ write_lock_irqsave(&device_info->lock, flags);
|
||||
+ list_add(&buf->node, &device_info->safe_buffers);
|
||||
+ write_unlock_irqrestore(&device_info->lock, flags);
|
||||
+
|
||||
+ return buf;
|
||||
+}
|
||||
+
|
||||
+/* determine if a buffer is from our "safe" pool */
|
||||
+static struct safe_buffer *
|
||||
+find_safe_buffer(struct dmabounce_device_info *device_info,
|
||||
+ dma_addr_t safe_dma_addr)
|
||||
+{
|
||||
+ struct safe_buffer *b, *rb = NULL;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ read_lock_irqsave(&device_info->lock, flags);
|
||||
+
|
||||
+ list_for_each_entry(b, &device_info->safe_buffers, node)
|
||||
+ if (b->safe_dma_addr <= safe_dma_addr &&
|
||||
+ b->safe_dma_addr + b->size > safe_dma_addr) {
|
||||
+ rb = b;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ read_unlock_irqrestore(&device_info->lock, flags);
|
||||
+ return rb;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+free_safe_buffer(struct dmabounce_device_info *device_info,
|
||||
+ struct safe_buffer *buf)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ write_lock_irqsave(&device_info->lock, flags);
|
||||
+ list_del(&buf->node);
|
||||
+ write_unlock_irqrestore(&device_info->lock, flags);
|
||||
+
|
||||
+ bounce_free(buf->pool, buf->safe, buf->size);
|
||||
+
|
||||
+ kfree(buf);
|
||||
+}
|
||||
+
|
||||
+/* ************************************************** */
|
||||
+
|
||||
+static struct safe_buffer *
|
||||
+find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
|
||||
+{
|
||||
+ if (!dev || !g_dmabounce_device_info)
|
||||
+ return NULL;
|
||||
+ if (dma_mapping_error(dev, dma_addr)) {
|
||||
+ dev_err(dev, "Trying to %s invalid mapping\n", where);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return find_safe_buffer(g_dmabounce_device_info, dma_addr);
|
||||
+}
|
||||
+
|
||||
+static dma_addr_t
|
||||
+map_single(struct device *dev, struct safe_buffer *buf, size_t size,
|
||||
+ enum dma_data_direction dir, unsigned long attrs)
|
||||
+{
|
||||
+ BUG_ON(buf->size != size);
|
||||
+ BUG_ON(buf->direction != dir);
|
||||
+
|
||||
+ dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
|
||||
+ (u64)buf->safe_dma_addr);
|
||||
+
|
||||
+ if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
|
||||
+ !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
|
||||
+ bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
|
||||
+ size);
|
||||
+
|
||||
+ return buf->safe_dma_addr;
|
||||
+}
|
||||
+
|
||||
+static dma_addr_t
|
||||
+unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
|
||||
+ enum dma_data_direction dir, unsigned long attrs)
|
||||
+{
|
||||
+ BUG_ON(buf->size != size);
|
||||
+ BUG_ON(buf->direction != dir);
|
||||
+
|
||||
+ if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
|
||||
+ !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
|
||||
+ dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
|
||||
+ (u64)buf->unsafe_dma_addr);
|
||||
+
|
||||
+ bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
|
||||
+ size);
|
||||
+ }
|
||||
+ return buf->unsafe_dma_addr;
|
||||
+}
|
||||
+
|
||||
+/* ************************************************** */
|
||||
+
|
||||
+/*
|
||||
+ * see if a buffer address is in an 'unsafe' range. if it is
|
||||
+ * allocate a 'safe' buffer and copy the unsafe buffer into it.
|
||||
+ * substitute the safe buffer for the unsafe one.
|
||||
+ * (basically move the buffer from an unsafe area to a safe one)
|
||||
+ */
|
||||
+static dma_addr_t
|
||||
+dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
|
||||
+ size_t size, enum dma_data_direction dir,
|
||||
+ unsigned long attrs)
|
||||
+{
|
||||
+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
|
||||
+ dma_addr_t dma_addr;
|
||||
+
|
||||
+ dma_addr = phys_to_dma(dev, page_to_phys(page)) + offset;
|
||||
+
|
||||
+ swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
|
||||
+ if (!is_device_dma_coherent(dev))
|
||||
+ __dma_map_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
|
||||
+
|
||||
+ if (device_info && (dma_addr + size) > device_info->threshold) {
|
||||
+ struct safe_buffer *buf;
|
||||
+
|
||||
+ buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
|
||||
+ if (!buf) {
|
||||
+ DO_STATS(device_info->fail_count++);
|
||||
+ return (~(dma_addr_t)0x0);
|
||||
+ }
|
||||
+
|
||||
+ DO_STATS(device_info->map_count++);
|
||||
+
|
||||
+ dma_addr = map_single(dev, buf, size, dir, attrs);
|
||||
+ }
|
||||
+ return dma_addr;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * see if a mapped address was really a "safe" buffer and if so, copy
|
||||
+ * the data from the safe buffer back to the unsafe buffer and free up
|
||||
+ * the safe buffer. (basically return things back to the way they
|
||||
+ * should be)
|
||||
+ */
|
||||
+static void
|
||||
+dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
+ enum dma_data_direction dir, unsigned long attrs)
|
||||
+{
|
||||
+ struct safe_buffer *buf;
|
||||
+
|
||||
+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
|
||||
+ if (buf) {
|
||||
+ DO_STATS(g_dmabounce_device_info->unmap_count++);
|
||||
+ dma_addr = unmap_single(dev, buf, size, dir, attrs);
|
||||
+ free_safe_buffer(g_dmabounce_device_info, buf);
|
||||
+ }
|
||||
+
|
||||
+ if (!is_device_dma_coherent(dev))
|
||||
+ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
|
||||
+ swiotlb_sync_single_for_cpu(dev, dma_addr, size, dir);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * A version of dmabounce_map_page that assumes the mapping has already
|
||||
+ * been created - intended for streaming operation.
|
||||
+ */
|
||||
+static void
|
||||
+dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct safe_buffer *buf;
|
||||
+
|
||||
+ swiotlb_sync_single_for_device(dev, dma_addr, size, dir);
|
||||
+ if (!is_device_dma_coherent(dev))
|
||||
+ __dma_map_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
|
||||
+
|
||||
+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
|
||||
+ if (buf) {
|
||||
+ DO_STATS(g_dmabounce_device_info->sync_dev_count++);
|
||||
+ map_single(dev, buf, size, dir, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
|
||||
+ * intended for streaming operation.
|
||||
+ */
|
||||
+static void
|
||||
+dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
|
||||
+ size_t size, enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct safe_buffer *buf;
|
||||
+
|
||||
+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
|
||||
+ if (buf) {
|
||||
+ DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
|
||||
+ dma_addr = unmap_single(dev, buf, size, dir, 0);
|
||||
+ }
|
||||
+
|
||||
+ if (!is_device_dma_coherent(dev))
|
||||
+ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dma_addr)), size, dir);
|
||||
+ swiotlb_sync_single_for_cpu(dev, dma_addr, size, dir);
|
||||
+}
|
||||
+
|
||||
+static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
|
||||
+{
|
||||
+ if (g_dmabounce_device_info)
|
||||
+ return 0;
|
||||
+
|
||||
+ return swiotlb_dma_supported(dev, dma_mask);
|
||||
+}
|
||||
+
|
||||
+static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
+{
|
||||
+ return swiotlb_dma_mapping_error(dev, dma_addr);
|
||||
+}
|
||||
+
|
||||
+static const struct dma_map_ops dmabounce_ops = {
|
||||
+ .alloc = arm64_dma_alloc,
|
||||
+ .free = arm64_dma_free,
|
||||
+ .mmap = arm64_dma_mmap,
|
||||
+ .get_sgtable = arm64_dma_get_sgtable,
|
||||
+ .map_page = dmabounce_map_page,
|
||||
+ .unmap_page = dmabounce_unmap_page,
|
||||
+ .sync_single_for_cpu = dmabounce_sync_for_cpu,
|
||||
+ .sync_single_for_device = dmabounce_sync_for_device,
|
||||
+ .map_sg = arm64_dma_map_sg,
|
||||
+ .unmap_sg = arm64_dma_unmap_sg,
|
||||
+ .sync_sg_for_cpu = arm64_dma_sync_sg_for_cpu,
|
||||
+ .sync_sg_for_device = arm64_dma_sync_sg_for_device,
|
||||
+ .dma_supported = dmabounce_dma_supported,
|
||||
+ .mapping_error = dmabounce_mapping_error,
|
||||
+};
|
||||
+
|
||||
+int brcm_pcie_bounce_init(struct device *dev,
|
||||
+ unsigned long buffer_size,
|
||||
+ dma_addr_t threshold)
|
||||
+{
|
||||
+ struct dmabounce_device_info *device_info;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Only support a single client */
|
||||
+ if (g_dmabounce_device_info)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ ret = bcm2838_dma40_memcpy_init();
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
|
||||
+ if (!device_info) {
|
||||
+ dev_err(dev,
|
||||
+ "Could not allocated dmabounce_device_info\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ ret = bounce_create(&device_info->pool, dev, buffer_size);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev,
|
||||
+ "dmabounce: could not allocate %ld byte DMA pool\n",
|
||||
+ buffer_size);
|
||||
+ goto err_bounce;
|
||||
+ }
|
||||
+
|
||||
+ device_info->dev = dev;
|
||||
+ device_info->threshold = threshold;
|
||||
+ INIT_LIST_HEAD(&device_info->safe_buffers);
|
||||
+ rwlock_init(&device_info->lock);
|
||||
+
|
||||
+ DO_STATS(device_info->map_count = 0);
|
||||
+ DO_STATS(device_info->unmap_count = 0);
|
||||
+ DO_STATS(device_info->sync_dev_count = 0);
|
||||
+ DO_STATS(device_info->sync_cpu_count = 0);
|
||||
+ DO_STATS(device_info->fail_count = 0);
|
||||
+ DO_STATS(device_info->attr_res =
|
||||
+ device_create_file(dev, &dev_attr_dmabounce_stats));
|
||||
+
|
||||
+ g_dmabounce_device_info = device_info;
|
||||
+
|
||||
+ dev_err(dev, "dmabounce: initialised - %ld kB, threshold %pad\n",
|
||||
+ buffer_size / 1024, &threshold);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ err_bounce:
|
||||
+ kfree(device_info);
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL(brcm_pcie_bounce_init);
|
||||
+
|
||||
+void brcm_pcie_bounce_uninit(struct device *dev)
|
||||
+{
|
||||
+ struct dmabounce_device_info *device_info = g_dmabounce_device_info;
|
||||
+
|
||||
+ g_dmabounce_device_info = NULL;
|
||||
+
|
||||
+ if (!device_info) {
|
||||
+ dev_warn(dev,
|
||||
+ "Never registered with dmabounce but attempting"
|
||||
+ "to unregister!\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!list_empty(&device_info->safe_buffers)) {
|
||||
+ dev_err(dev,
|
||||
+ "Removing from dmabounce with pending buffers!\n");
|
||||
+ BUG();
|
||||
+ }
|
||||
+
|
||||
+ bounce_destroy(&device_info->pool);
|
||||
+
|
||||
+ DO_STATS(if (device_info->attr_res == 0)
|
||||
+ device_remove_file(dev, &dev_attr_dmabounce_stats));
|
||||
+
|
||||
+ kfree(device_info);
|
||||
+}
|
||||
+EXPORT_SYMBOL(brcm_pcie_bounce_uninit);
|
||||
+
|
||||
+int brcm_pcie_bounce_register_dev(struct device *dev)
|
||||
+{
|
||||
+ set_dma_ops(dev, &dmabounce_ops);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
|
||||
+
|
||||
+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
|
||||
+MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
|
||||
index f99ab05ab477..f279ed67e4e1 100644
|
||||
--- a/drivers/pci/controller/pcie-brcmstb.c
|
||||
+++ b/drivers/pci/controller/pcie-brcmstb.c
|
||||
@@ -617,28 +617,6 @@ static const struct dma_map_ops brcm_dma_ops = {
|
||||
|
||||
static void brcm_set_dma_ops(struct device *dev)
|
||||
{
|
||||
- int ret;
|
||||
-
|
||||
- if (IS_ENABLED(CONFIG_ARM64)) {
|
||||
- /*
|
||||
- * We are going to invoke get_dma_ops(). That
|
||||
- * function, at this point in time, invokes
|
||||
- * get_arch_dma_ops(), and for ARM64 that function
|
||||
- * returns a pointer to dummy_dma_ops. So then we'd
|
||||
- * like to call arch_setup_dma_ops(), but that isn't
|
||||
- * exported. Instead, we call of_dma_configure(),
|
||||
- * which is exported, and this calls
|
||||
- * arch_setup_dma_ops(). Once we do this the call to
|
||||
- * get_dma_ops() will work properly because
|
||||
- * dev->dma_ops will be set.
|
||||
- */
|
||||
- ret = of_dma_configure(dev, dev->of_node, true);
|
||||
- if (ret) {
|
||||
- dev_err(dev, "of_dma_configure() failed: %d\n", ret);
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
arch_dma_ops = get_dma_ops(dev);
|
||||
if (!arch_dma_ops) {
|
||||
dev_err(dev, "failed to get arch_dma_ops\n");
|
||||
@@ -657,12 +635,12 @@ static int brcmstb_platform_notifier(struct notifier_block *nb,
|
||||
extern unsigned long max_pfn;
|
||||
struct device *dev = __dev;
|
||||
const char *rc_name = "0000:00:00.0";
|
||||
+ int ret;
|
||||
|
||||
switch (event) {
|
||||
case BUS_NOTIFY_ADD_DEVICE:
|
||||
if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
|
||||
strcmp(dev->kobj.name, rc_name)) {
|
||||
- int ret;
|
||||
|
||||
ret = brcm_pcie_bounce_register_dev(dev);
|
||||
if (ret) {
|
||||
@@ -671,6 +649,12 @@ static int brcmstb_platform_notifier(struct notifier_block *nb,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
+ } else if (IS_ENABLED(CONFIG_ARM64)) {
|
||||
+ ret = of_dma_configure(dev, dev->of_node, true);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "of_dma_configure() failed: %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
brcm_set_dma_ops(dev);
|
||||
return NOTIFY_OK;
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
From fc5826fb999e0b32900d1f487e90c27a92010214 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.org>
|
||||
Date: Thu, 15 Aug 2019 12:02:34 +0100
|
||||
Subject: [PATCH 826/826] configs: arm64/vcm2711: Enable V3D
|
||||
|
||||
Enable the V3D driver, which depends on BCM2835_POWER.
|
||||
|
||||
Originally submitted by GitHub user 'phire' in a slightly different
|
||||
form.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/pull/3063
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
---
|
||||
arch/arm64/configs/bcm2711_defconfig | 2 ++
|
||||
drivers/gpu/drm/v3d/Kconfig | 2 +-
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig
|
||||
index e06ba27ccb25..200f66c006d6 100644
|
||||
--- a/arch/arm64/configs/bcm2711_defconfig
|
||||
+++ b/arch/arm64/configs/bcm2711_defconfig
|
||||
@@ -791,6 +791,7 @@ CONFIG_DRM_LOAD_EDID_FIRMWARE=y
|
||||
CONFIG_DRM_UDL=m
|
||||
CONFIG_DRM_PANEL_SIMPLE=m
|
||||
CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
|
||||
+CONFIG_DRM_V3D=m
|
||||
CONFIG_DRM_VC4=m
|
||||
CONFIG_DRM_TINYDRM=m
|
||||
CONFIG_TINYDRM_MI0283QT=m
|
||||
@@ -1135,6 +1136,7 @@ CONFIG_VIDEO_BCM2835=m
|
||||
CONFIG_MAILBOX=y
|
||||
CONFIG_BCM2835_MBOX=y
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
+CONFIG_BCM2835_POWER=y
|
||||
CONFIG_RASPBERRYPI_POWER=y
|
||||
CONFIG_EXTCON=m
|
||||
CONFIG_EXTCON_ARIZONA=m
|
||||
diff --git a/drivers/gpu/drm/v3d/Kconfig b/drivers/gpu/drm/v3d/Kconfig
|
||||
index 1552bf552c94..2967459b8fb0 100644
|
||||
--- a/drivers/gpu/drm/v3d/Kconfig
|
||||
+++ b/drivers/gpu/drm/v3d/Kconfig
|
||||
@@ -1,6 +1,6 @@
|
||||
config DRM_V3D
|
||||
tristate "Broadcom V3D 3.x and newer"
|
||||
- depends on ARCH_BCM || ARCH_BCMSTB || COMPILE_TEST
|
||||
+ depends on ARCH_BCM || ARCH_BCMSTB || ARCH_BCM2835 || COMPILE_TEST
|
||||
depends on DRM
|
||||
depends on COMMON_CLK
|
||||
depends on MMU
|
||||
--
|
||||
2.22.0
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
From d9aa3902c1fb7163edf1812dd0e03ed5a7e129ed Mon Sep 17 00:00:00 2001
|
||||
From: Yaroslav Rosomakho <yaroslavros@gmail.com>
|
||||
Date: Mon, 19 Aug 2019 01:26:13 +0200
|
||||
Subject: [PATCH] This should fix DMA leaks that lead to swiotlb buffer
|
||||
overflow errors on bcm2835-mmc under ARM64.
|
||||
|
||||
Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com>
|
||||
---
|
||||
drivers/mmc/host/bcm2835-mmc.c | 21 ++++++++++++++-------
|
||||
1 file changed, 14 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c
|
||||
index 68daa59d313b4..1311c8268e83e 100644
|
||||
--- a/drivers/mmc/host/bcm2835-mmc.c
|
||||
+++ b/drivers/mmc/host/bcm2835-mmc.c
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of_dma.h>
|
||||
+#include <linux/swiotlb.h>
|
||||
|
||||
#include "sdhci.h"
|
||||
|
||||
@@ -344,16 +345,17 @@ static void bcm2835_mmc_dma_complete(void *param)
|
||||
|
||||
host->use_dma = false;
|
||||
|
||||
- if (host->data && !(host->data->flags & MMC_DATA_WRITE)) {
|
||||
- /* otherwise handled in SDHCI IRQ */
|
||||
+ if (host->data) {
|
||||
dma_chan = host->dma_chan_rxtx;
|
||||
- dir_data = DMA_FROM_DEVICE;
|
||||
-
|
||||
+ if (host->data->flags & MMC_DATA_WRITE)
|
||||
+ dir_data = DMA_TO_DEVICE;
|
||||
+ else
|
||||
+ dir_data = DMA_FROM_DEVICE;
|
||||
dma_unmap_sg(dma_chan->device->dev,
|
||||
host->data->sg, host->data->sg_len,
|
||||
dir_data);
|
||||
-
|
||||
- bcm2835_mmc_finish_data(host);
|
||||
+ if (! (host->data->flags & MMC_DATA_WRITE))
|
||||
+ bcm2835_mmc_finish_data(host);
|
||||
} else if (host->wait_for_dma) {
|
||||
host->wait_for_dma = false;
|
||||
tasklet_schedule(&host->finish_tasklet);
|
||||
@@ -539,6 +541,8 @@ static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host)
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
dmaengine_submit(desc);
|
||||
dma_async_issue_pending(dma_chan);
|
||||
+ } else {
|
||||
+ dma_unmap_sg(dma_chan->device->dev, host->data->sg, len, dir_data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1374,7 +1378,10 @@ static int bcm2835_mmc_add_host(struct bcm2835_host *host)
|
||||
}
|
||||
#endif
|
||||
mmc->max_segs = 128;
|
||||
- mmc->max_req_size = 524288;
|
||||
+ if (swiotlb_max_segment())
|
||||
+ mmc->max_req_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE;
|
||||
+ else
|
||||
+ mmc->max_req_size = 524288;
|
||||
mmc->max_seg_size = mmc->max_req_size;
|
||||
mmc->max_blk_size = 512;
|
||||
mmc->max_blk_count = 65535;
|
Loading…
Add table
Add a link
Reference in a new issue