1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Update OpenWrt

This commit is contained in:
Ycarus (Yannick Chabanois) 2019-08-28 21:13:55 +02:00
parent 0dd5bbf0fa
commit da818da21b
43 changed files with 1 additions and 5163 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;