diff --git a/0000-raspberrypi-kernel.patch b/0000-raspberrypi-kernel.patch index 6a8f7b5694df7633205d9391a38d1f84474d2997..409add53fdbd3bf0cba59b65b102f48fd443f637 100644 --- a/0000-raspberrypi-kernel.patch +++ b/0000-raspberrypi-kernel.patch @@ -1,7 +1,7 @@ -From 1ccad414b11e455ad464b4a9e9b3495663f008fb Mon Sep 17 00:00:00 2001 -From: Fang Yafen -Date: Wed, 20 Oct 2021 00:58:36 +0800 -Subject: [PATCH] apply RPi patch of 5.10.74 +From 9beea4e2f575848931e196afedc3ef164e23fa09 Mon Sep 17 00:00:00 2001 +From: Yafen +Date: Mon, 5 Jun 2023 21:10:22 +0800 +Subject: [PATCH] apply RPi patch of 5.10.110(openEuler 5.10.0-153.1.0) --- .../admin-guide/media/bcm2835-isp.rst | 127 + @@ -11,7 +11,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../bindings/display/brcm,bcm2835-hdmi.yaml | 118 +- .../bindings/display/brcm,bcm2835-vc4.yaml | 5 + .../bindings/display/brcm,bcm2835-vec.yaml | 4 +- - .../bindings/display/panel/panel-simple.yaml | 2 + + .../bindings/display/panel/panel-simple.yaml | 4 + .../devicetree/bindings/hwmon/rpi-poe-fan.txt | 55 + .../bindings/media/bcm2835-unicam.txt | 85 + .../devicetree/bindings/media/i2c/imx219.txt | 59 + @@ -29,11 +29,12 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../bindings/power/reset/gpio-poweroff.txt | 1 + .../devicetree/bindings/serial/pl011.yaml | 6 + .../devicetree/bindings/vendor-prefixes.txt | 463 ++ - .../devicetree/bindings/vendor-prefixes.yaml | 2 + + .../devicetree/bindings/vendor-prefixes.yaml | 4 + .../devicetree/configfs-overlays.txt | 31 + Documentation/hwmon/rpi-poe-fan | 15 + .../userspace-api/media/drivers/index.rst | 1 + .../media/v4l/ext-ctrls-codec.rst | 46 +- + .../media/v4l/ext-ctrls-image-source.rst | 20 + .../userspace-api/media/v4l/meta-formats.rst | 2 + .../media/v4l/pixfmt-compressed.rst | 1 + .../v4l/pixfmt-meta-bcm2835-isp-stats.rst | 41 + @@ -42,38 +43,41 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../userspace-api/media/v4l/pixfmt-nv12.rst | 14 +- .../userspace-api/media/v4l/pixfmt-y12p.rst | 45 + .../userspace-api/media/v4l/pixfmt-y14p.rst | 54 + - .../media/v4l/subdev-formats.rst | 107 + + .../media/v4l/subdev-formats.rst | 144 + .../userspace-api/media/v4l/yuv-formats.rst | 3 + MAINTAINERS | 48 + Makefile | 3 + - arch/arm/boot/dts/Makefile | 28 +- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 129 + - arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts | 132 + - arch/arm/boot/dts/bcm2708-rpi-b.dts | 119 + + arch/arm/boot/dts/Makefile | 31 +- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 131 + + arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts | 134 + + arch/arm/boot/dts/bcm2708-rpi-b.dts | 121 + arch/arm/boot/dts/bcm2708-rpi-bt.dtsi | 26 + - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 112 + - arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 18 + - arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 169 + - arch/arm/boot/dts/bcm2708-rpi-zero.dts | 123 + + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 106 + + arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 22 + + arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 178 + + arch/arm/boot/dts/bcm2708-rpi-zero.dts | 125 + arch/arm/boot/dts/bcm2708-rpi.dtsi | 36 + arch/arm/boot/dts/bcm2708.dtsi | 12 + - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 129 + + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 131 + arch/arm/boot/dts/bcm2709-rpi.dtsi | 5 + arch/arm/boot/dts/bcm2709.dtsi | 22 + arch/arm/boot/dts/bcm270x-rpi.dtsi | 155 + - arch/arm/boot/dts/bcm270x.dtsi | 217 + - arch/arm/boot/dts/bcm2710-rpi-2-b.dts | 129 + - arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 201 + - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 203 + - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 148 + + arch/arm/boot/dts/bcm270x.dtsi | 272 + + arch/arm/boot/dts/bcm2710-rpi-2-b.dts | 131 + + arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 210 + + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 212 + + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 146 + + arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts | 199 + + arch/arm/boot/dts/bcm2710-rpi-zero-2.dts | 1 + arch/arm/boot/dts/bcm2710.dtsi | 25 + - arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 326 +- - arch/arm/boot/dts/bcm2711-rpi-400.dts | 636 ++ - arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 659 ++ + arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 330 +- + arch/arm/boot/dts/bcm2711-rpi-400.dts | 637 ++ + arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 652 ++ + arch/arm/boot/dts/bcm2711-rpi-cm4s.dts | 477 ++ arch/arm/boot/dts/bcm2711-rpi.dtsi | 205 + arch/arm/boot/dts/bcm2711.dtsi | 72 +- arch/arm/boot/dts/bcm271x-rpi-bt.dtsi | 26 + - arch/arm/boot/dts/bcm2835-common.dtsi | 12 +- + arch/arm/boot/dts/bcm2835-common.dtsi | 14 +- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts | 5 + arch/arm/boot/dts/bcm2835-rpi-a.dts | 7 + arch/arm/boot/dts/bcm2835-rpi-b-plus.dts | 5 + @@ -89,7 +93,6 @@ Subject: [PATCH] apply RPi patch of 5.10.74 arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 5 + arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 5 + arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 5 + - .../boot/dts/bcm283x-rpi-cam1-regulator.dtsi | 10 + arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi | 4 + arch/arm/boot/dts/bcm283x-rpi-csi1-2lane.dtsi | 4 + arch/arm/boot/dts/bcm283x-rpi-csi1-4lane.dtsi | 4 + @@ -97,8 +100,8 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../boot/dts/bcm283x-rpi-i2c0mux_0_44.dtsi | 4 + .../boot/dts/bcm283x-rpi-usb-peripheral.dtsi | 7 - arch/arm/boot/dts/bcm283x.dtsi | 34 +- - arch/arm/boot/dts/overlays/Makefile | 252 + - arch/arm/boot/dts/overlays/README | 3576 +++++++++ + arch/arm/boot/dts/overlays/Makefile | 257 + + arch/arm/boot/dts/overlays/README | 3861 +++++++++ .../arm/boot/dts/overlays/act-led-overlay.dts | 27 + .../dts/overlays/adafruit-st7735r-overlay.dts | 83 + .../boot/dts/overlays/adafruit18-overlay.dts | 55 + @@ -107,7 +110,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../arm/boot/dts/overlays/ads1015-overlay.dts | 98 + .../arm/boot/dts/overlays/ads1115-overlay.dts | 103 + .../arm/boot/dts/overlays/ads7846-overlay.dts | 89 + - .../boot/dts/overlays/adv7282m-overlay.dts | 65 + + .../boot/dts/overlays/adv7282m-overlay.dts | 73 + .../boot/dts/overlays/adv728x-m-overlay.dts | 37 + .../overlays/akkordion-iqdacplus-overlay.dts | 49 + .../allo-boss-dac-pcm512x-audio-overlay.dts | 59 + @@ -130,6 +133,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../arm/boot/dts/overlays/cap1106-overlay.dts | 52 + .../boot/dts/overlays/chipdip-dac-overlay.dts | 46 + arch/arm/boot/dts/overlays/cma-overlay.dts | 36 + + .../dts/overlays/cutiepi-panel-overlay.dts | 117 + arch/arm/boot/dts/overlays/dht11-overlay.dts | 41 + .../dts/overlays/dionaudio-loco-overlay.dts | 39 + .../overlays/dionaudio-loco-v2-overlay.dts | 49 + @@ -141,11 +145,12 @@ Subject: [PATCH] apply RPi patch of 5.10.74 arch/arm/boot/dts/overlays/draws-overlay.dts | 208 + .../arm/boot/dts/overlays/dwc-otg-overlay.dts | 14 + arch/arm/boot/dts/overlays/dwc2-overlay.dts | 26 + - .../boot/dts/overlays/edt-ft5406-overlay.dts | 10 + - arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 55 + + .../boot/dts/overlays/edt-ft5406-overlay.dts | 26 + + arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 47 + .../boot/dts/overlays/enc28j60-overlay.dts | 53 + .../dts/overlays/enc28j60-spi2-overlay.dts | 47 + .../arm/boot/dts/overlays/exc3000-overlay.dts | 48 + + arch/arm/boot/dts/overlays/fbtft-overlay.dts | 611 ++ .../boot/dts/overlays/fe-pi-audio-overlay.dts | 70 + .../boot/dts/overlays/fsm-demo-overlay.dts | 104 + .../boot/dts/overlays/ghost-amp-overlay.dts | 145 + @@ -158,7 +163,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../boot/dts/overlays/gpio-led-overlay.dts | 97 + .../overlays/gpio-no-bank0-irq-overlay.dts | 14 + .../boot/dts/overlays/gpio-no-irq-overlay.dts | 14 + - .../dts/overlays/gpio-poweroff-overlay.dts | 37 + + .../dts/overlays/gpio-poweroff-overlay.dts | 39 + .../dts/overlays/gpio-shutdown-overlay.dts | 86 + .../boot/dts/overlays/hd44780-lcd-overlay.dts | 46 + .../hdmi-backlight-hwhack-gpio-overlay.dts | 47 + @@ -184,7 +189,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../arm/boot/dts/overlays/i2c-rtc-common.dtsi | 323 + .../dts/overlays/i2c-rtc-gpio-overlay.dts | 31 + .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 34 + - .../boot/dts/overlays/i2c-sensor-overlay.dts | 320 + + .../boot/dts/overlays/i2c-sensor-overlay.dts | 340 + arch/arm/boot/dts/overlays/i2c0-overlay.dts | 83 + arch/arm/boot/dts/overlays/i2c1-overlay.dts | 44 + arch/arm/boot/dts/overlays/i2c3-overlay.dts | 36 + @@ -193,18 +198,18 @@ Subject: [PATCH] apply RPi patch of 5.10.74 arch/arm/boot/dts/overlays/i2c6-overlay.dts | 36 + .../dts/overlays/i2s-gpio28-31-overlay.dts | 18 + .../boot/dts/overlays/ilitek251x-overlay.dts | 45 + - arch/arm/boot/dts/overlays/imx219-overlay.dts | 115 + + arch/arm/boot/dts/overlays/imx219-overlay.dts | 96 + arch/arm/boot/dts/overlays/imx290-overlay.dts | 32 + - .../boot/dts/overlays/imx290_327-overlay.dtsi | 144 + + .../boot/dts/overlays/imx290_327-overlay.dtsi | 125 + arch/arm/boot/dts/overlays/imx378-overlay.dts | 10 + arch/arm/boot/dts/overlays/imx477-overlay.dts | 10 + - .../boot/dts/overlays/imx477_378-overlay.dtsi | 110 + - arch/arm/boot/dts/overlays/imx519-overlay.dts | 115 + + .../boot/dts/overlays/imx477_378-overlay.dtsi | 99 + + arch/arm/boot/dts/overlays/imx519-overlay.dts | 96 + .../dts/overlays/iqaudio-codec-overlay.dts | 42 + .../boot/dts/overlays/iqaudio-dac-overlay.dts | 46 + .../dts/overlays/iqaudio-dacplus-overlay.dts | 49 + .../iqaudio-digi-wm8804-audio-overlay.dts | 47 + - .../arm/boot/dts/overlays/irs1125-overlay.dts | 85 + + .../arm/boot/dts/overlays/irs1125-overlay.dts | 90 + .../dts/overlays/jedec-spi-nor-overlay.dts | 309 + .../dts/overlays/justboom-both-overlay.dts | 65 + .../dts/overlays/justboom-dac-overlay.dts | 46 + @@ -236,13 +241,13 @@ Subject: [PATCH] apply RPi patch of 5.10.74 arch/arm/boot/dts/overlays/mmc-overlay.dts | 46 + .../arm/boot/dts/overlays/mpu6050-overlay.dts | 29 + .../arm/boot/dts/overlays/mz61581-overlay.dts | 117 + - arch/arm/boot/dts/overlays/ov5647-overlay.dts | 94 + - arch/arm/boot/dts/overlays/ov7251-overlay.dts | 113 + - arch/arm/boot/dts/overlays/ov9281-overlay.dts | 113 + - arch/arm/boot/dts/overlays/overlay_map.dts | 158 + + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 99 + + arch/arm/boot/dts/overlays/ov7251-overlay.dts | 94 + + arch/arm/boot/dts/overlays/ov9281-overlay.dts | 95 + + arch/arm/boot/dts/overlays/overlay_map.dts | 166 + .../arm/boot/dts/overlays/papirus-overlay.dts | 89 + .../arm/boot/dts/overlays/pca953x-overlay.dts | 240 + - .../dts/overlays/pcie-32bit-dma-overlay.dts | 18 + + .../dts/overlays/pcie-32bit-dma-overlay.dts | 38 + arch/arm/boot/dts/overlays/pibell-overlay.dts | 81 + .../dts/overlays/pifacedigital-overlay.dts | 144 + .../arm/boot/dts/overlays/pifi-40-overlay.dts | 50 + @@ -293,6 +298,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../dts/overlays/spi-gpio35-39-overlay.dts | 31 + .../dts/overlays/spi-gpio40-45-overlay.dts | 36 + .../arm/boot/dts/overlays/spi-rtc-overlay.dts | 75 + + .../boot/dts/overlays/spi0-0cs-overlay.dts | 39 + .../boot/dts/overlays/spi0-1cs-overlay.dts | 42 + .../boot/dts/overlays/spi0-2cs-overlay.dts | 37 + .../boot/dts/overlays/spi1-1cs-overlay.dts | 57 + @@ -316,7 +322,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../dts/overlays/superaudioboard-overlay.dts | 73 + arch/arm/boot/dts/overlays/sx150x-overlay.dts | 1706 ++++ .../dts/overlays/tc358743-audio-overlay.dts | 52 + - .../boot/dts/overlays/tc358743-overlay.dts | 107 + + .../boot/dts/overlays/tc358743-overlay.dts | 109 + .../boot/dts/overlays/tinylcd35-overlay.dts | 222 + .../boot/dts/overlays/tpm-slb9670-overlay.dts | 44 + arch/arm/boot/dts/overlays/uart0-overlay.dts | 32 + @@ -331,23 +337,26 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../dts/overlays/upstream-pi4-overlay.dts | 137 + .../dts/overlays/vc4-fkms-v3d-overlay.dts | 40 + .../dts/overlays/vc4-fkms-v3d-pi4-overlay.dts | 44 + - .../vc4-kms-dpi-at056tn53v1-overlay.dts | 44 + + .../overlays/vc4-kms-dpi-generic-overlay.dts | 74 + + .../overlays/vc4-kms-dpi-panel-overlay.dts | 69 + + arch/arm/boot/dts/overlays/vc4-kms-dpi.dtsi | 111 + .../overlays/vc4-kms-dsi-7inch-overlay.dts | 118 + .../vc4-kms-dsi-lt070me05000-overlay.dts | 69 + .../vc4-kms-dsi-lt070me05000-v2-overlay.dts | 64 + - .../overlays/vc4-kms-kippah-7inch-overlay.dts | 43 + + .../overlays/vc4-kms-kippah-7inch-overlay.dts | 26 + .../boot/dts/overlays/vc4-kms-v3d-overlay.dts | 123 + .../dts/overlays/vc4-kms-v3d-pi4-overlay.dts | 197 + .../dts/overlays/vc4-kms-vga666-overlay.dts | 100 + arch/arm/boot/dts/overlays/vga666-overlay.dts | 30 + + arch/arm/boot/dts/overlays/vl805-overlay.dts | 18 + .../arm/boot/dts/overlays/w1-gpio-overlay.dts | 40 + .../dts/overlays/w1-gpio-pullup-overlay.dts | 42 + arch/arm/boot/dts/overlays/w5500-overlay.dts | 63 + .../arm/boot/dts/overlays/wittypi-overlay.dts | 44 + .../dts/overlays/wm8960-soundcard-overlay.dts | 82 + - arch/arm/configs/bcm2709_defconfig | 1510 ++++ - arch/arm/configs/bcm2711_defconfig | 1550 ++++ - arch/arm/configs/bcmrpi_defconfig | 1523 ++++ + arch/arm/configs/bcm2709_defconfig | 1533 ++++ + arch/arm/configs/bcm2711_defconfig | 1557 ++++ + arch/arm/configs/bcmrpi_defconfig | 1528 ++++ arch/arm/configs/multi_v7_defconfig | 1 + arch/arm/include/asm/cacheflush.h | 21 + arch/arm/include/asm/glue-cache.h | 2 + @@ -363,10 +372,10 @@ Subject: [PATCH] apply RPi patch of 5.10.74 arch/arm/lib/copy_from_user.S | 4 +- arch/arm/lib/exports_rpi.c | 37 + arch/arm/lib/memcmp_rpi.S | 285 + - arch/arm/lib/memcpy_rpi.S | 61 + - arch/arm/lib/memcpymove.h | 506 ++ - arch/arm/lib/memmove_rpi.S | 61 + - arch/arm/lib/memset_rpi.S | 128 + + arch/arm/lib/memcpy_rpi.S | 63 + + arch/arm/lib/memcpymove.h | 488 ++ + arch/arm/lib/memmove_rpi.S | 63 + + arch/arm/lib/memset_rpi.S | 130 + arch/arm/lib/uaccess_with_memcpy.c | 130 +- arch/arm/mach-bcm/Kconfig | 10 + arch/arm/mach-bcm/board_bcm2835.c | 109 + @@ -375,29 +384,32 @@ Subject: [PATCH] apply RPi patch of 5.10.74 arch/arm/mm/proc-macros.S | 2 + arch/arm/mm/proc-syms.c | 3 + arch/arm/mm/proc-v6.S | 15 +- - arch/arm/mm/proc-v7.S | 8 + arch/arm/vfp/vfpmodule.c | 25 +- arch/arm64/Kconfig.platforms | 1 + arch/arm64/boot/dts/Makefile | 2 + - arch/arm64/boot/dts/broadcom/Makefile | 15 +- + arch/arm64/boot/dts/broadcom/Makefile | 18 +- .../boot/dts/broadcom/bcm2710-rpi-2-b.dts | 1 + .../dts/broadcom/bcm2710-rpi-3-b-plus.dts | 1 + .../boot/dts/broadcom/bcm2710-rpi-3-b.dts | 1 + .../boot/dts/broadcom/bcm2710-rpi-cm3.dts | 1 + + .../dts/broadcom/bcm2710-rpi-zero-2-w.dts | 1 + + .../boot/dts/broadcom/bcm2710-rpi-zero-2.dts | 1 + .../boot/dts/broadcom/bcm2711-rpi-4-b.dts | 3 +- .../boot/dts/broadcom/bcm2711-rpi-400.dts | 1 + .../boot/dts/broadcom/bcm2711-rpi-cm4.dts | 1 + + .../boot/dts/broadcom/bcm2711-rpi-cm4s.dts | 1 + .../dts/broadcom/bcm283x-rpi-csi1-2lane.dtsi | 1 + .../dts/broadcom/bcm283x-rpi-lan7515.dtsi | 1 + arch/arm64/boot/dts/overlays | 1 + - arch/arm64/configs/bcm2711_defconfig | 1556 ++++ - arch/arm64/configs/bcmrpi3_defconfig | 1402 ++++ + arch/arm64/configs/bcm2711_defconfig | 1566 ++++ + arch/arm64/configs/bcmrpi3_defconfig | 1411 ++++ arch/arm64/configs/defconfig | 1 + arch/arm64/crypto/aes-cipher-glue.c | 10 + arch/arm64/crypto/aes-glue.c | 4 +- arch/arm64/crypto/aes-neonbs-glue.c | 5 - arch/arm64/kernel/armv8_deprecated.c | 5 + arch/arm64/kernel/cpuinfo.c | 25 + + drivers/bluetooth/btusb.c | 8 + drivers/bluetooth/hci_h5.c | 3 +- drivers/char/Kconfig | 2 + drivers/char/Makefile | 1 + @@ -413,8 +425,8 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/char/hw_random/iproc-rng200.c | 78 +- drivers/clk/Kconfig | 6 + drivers/clk/Makefile | 3 + - drivers/clk/bcm/clk-bcm2835.c | 187 +- - drivers/clk/bcm/clk-raspberrypi.c | 3 +- + drivers/clk/bcm/clk-bcm2835.c | 202 +- + drivers/clk/bcm/clk-raspberrypi.c | 7 +- drivers/clk/clk-allo-dac.c | 161 + drivers/clk/clk-hifiberry-dachd.c | 333 + drivers/clk/clk-hifiberry-dacpro.c | 160 + @@ -441,12 +453,15 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/gpu/drm/armada/armada_crtc.c | 23 +- drivers/gpu/drm/ast/ast_mode.c | 19 +- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 12 +- + drivers/gpu/drm/bridge/panel.c | 4 + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 20 +- drivers/gpu/drm/drm_atomic_helper.c | 106 +- - drivers/gpu/drm/drm_color_mgmt.c | 111 +- + drivers/gpu/drm/drm_color_mgmt.c | 114 +- drivers/gpu/drm/drm_connector.c | 70 + + drivers/gpu/drm/drm_edid.c | 15 +- drivers/gpu/drm/drm_fourcc.c | 3 + drivers/gpu/drm/drm_framebuffer.c | 16 +- + drivers/gpu/drm/drm_panel.c | 15 +- drivers/gpu/drm/drm_probe_helper.c | 111 +- drivers/gpu/drm/drm_simple_kms_helper.c | 14 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 16 +- @@ -463,10 +478,10 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../gpu/drm/i915/display/intel_connector.c | 3 +- drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/display/intel_dp_mst.c | 7 +- - drivers/gpu/drm/i915/display/intel_hdmi.c | 3 +- + drivers/gpu/drm/i915/display/intel_hdmi.c | 5 +- drivers/gpu/drm/imx/dcss/dcss-crtc.c | 13 +- drivers/gpu/drm/imx/ipuv3-crtc.c | 16 +- - drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 35 +- + drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 37 +- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 21 +- drivers/gpu/drm/meson/meson_crtc.c | 12 +- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 34 +- @@ -476,9 +491,10 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/gpu/drm/nouveau/dispnv50/disp.c | 5 +- drivers/gpu/drm/nouveau/dispnv50/head.c | 9 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 22 +- + drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 253 +- .../gpu/drm/panel/panel-jdi-lt070me05000.c | 18 +- - .../drm/panel/panel-raspberrypi-touchscreen.c | 49 +- - drivers/gpu/drm/panel/panel-simple.c | 63 + + .../drm/panel/panel-raspberrypi-touchscreen.c | 36 +- + drivers/gpu/drm/panel/panel-simple.c | 106 +- drivers/gpu/drm/qxl/qxl_display.c | 6 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 22 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 19 +- @@ -498,25 +514,25 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/gpu/drm/vboxvideo/vbox_mode.c | 6 +- drivers/gpu/drm/vc4/Kconfig | 1 + drivers/gpu/drm/vc4/Makefile | 1 + - drivers/gpu/drm/vc4/vc4_crtc.c | 232 +- + drivers/gpu/drm/vc4/vc4_crtc.c | 276 +- drivers/gpu/drm/vc4/vc4_debugfs.c | 7 +- - drivers/gpu/drm/vc4/vc4_dpi.c | 14 +- - drivers/gpu/drm/vc4/vc4_drv.c | 81 +- - drivers/gpu/drm/vc4/vc4_drv.h | 36 +- - drivers/gpu/drm/vc4/vc4_dsi.c | 277 +- + drivers/gpu/drm/vc4/vc4_dpi.c | 113 +- + drivers/gpu/drm/vc4/vc4_drv.c | 66 +- + drivers/gpu/drm/vc4/vc4_drv.h | 95 +- + drivers/gpu/drm/vc4/vc4_dsi.c | 73 +- drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1992 +++++ drivers/gpu/drm/vc4/vc4_gem.c | 3 +- - drivers/gpu/drm/vc4/vc4_hdmi.c | 1218 ++- - drivers/gpu/drm/vc4/vc4_hdmi.h | 66 +- - drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 8 +- - drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 27 +- - drivers/gpu/drm/vc4/vc4_hvs.c | 63 +- - drivers/gpu/drm/vc4/vc4_kms.c | 178 +- + drivers/gpu/drm/vc4/vc4_hdmi.c | 2294 +++++- + drivers/gpu/drm/vc4/vc4_hdmi.h | 148 +- + drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 45 +- + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 35 +- + drivers/gpu/drm/vc4/vc4_hvs.c | 309 +- + drivers/gpu/drm/vc4/vc4_kms.c | 181 +- drivers/gpu/drm/vc4/vc4_perfmon.c | 2 +- - drivers/gpu/drm/vc4/vc4_plane.c | 211 +- - drivers/gpu/drm/vc4/vc4_regs.h | 49 +- - drivers/gpu/drm/vc4/vc4_txp.c | 22 +- - drivers/gpu/drm/vc4/vc4_vec.c | 281 +- + drivers/gpu/drm/vc4/vc4_plane.c | 312 +- + drivers/gpu/drm/vc4/vc4_regs.h | 90 +- + drivers/gpu/drm/vc4/vc4_txp.c | 24 +- + drivers/gpu/drm/vc4/vc4_vec.c | 393 +- drivers/gpu/drm/vc4/vc_image_types.h | 175 + drivers/gpu/drm/virtio/virtgpu_display.c | 8 +- drivers/gpu/drm/vkms/vkms_crtc.c | 24 +- @@ -538,12 +554,12 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/i2c/busses/Kconfig | 19 + drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-bcm2708.c | 512 ++ - drivers/i2c/busses/i2c-bcm2835.c | 111 +- + drivers/i2c/busses/i2c-bcm2835.c | 115 +- drivers/i2c/busses/i2c-gpio.c | 4 +- drivers/input/joystick/Kconfig | 8 + drivers/input/joystick/Makefile | 2 +- drivers/input/joystick/rpisense-js.c | 153 + - drivers/input/touchscreen/edt-ft5x06.c | 55 +- + drivers/input/touchscreen/edt-ft5x06.c | 85 +- drivers/irqchip/irq-bcm2835.c | 104 +- drivers/irqchip/irq-bcm2836.c | 28 +- drivers/leds/leds-gpio.c | 17 +- @@ -552,33 +568,34 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/leds/trigger/ledtrig-actpwr.c | 190 + drivers/leds/trigger/ledtrig-input.c | 55 + drivers/mailbox/bcm2835-mailbox.c | 18 +- - drivers/mailbox/mailbox.c | 12 +- + drivers/mailbox/mailbox.c | 5 +- .../media/common/videobuf2/videobuf2-core.c | 21 +- drivers/media/i2c/Kconfig | 45 + drivers/media/i2c/Makefile | 4 + drivers/media/i2c/adv7180.c | 14 + - drivers/media/i2c/imx219.c | 229 +- + drivers/media/i2c/imx219.c | 235 +- drivers/media/i2c/imx290.c | 613 +- - drivers/media/i2c/imx477.c | 2284 ++++++ + drivers/media/i2c/imx477.c | 2309 ++++++ drivers/media/i2c/imx519.c | 2091 +++++ drivers/media/i2c/irs1125.c | 1200 +++ drivers/media/i2c/irs1125.h | 95 + - drivers/media/i2c/ov5647.c | 1216 ++- - drivers/media/i2c/ov7251.c | 12 +- - drivers/media/i2c/ov9281.c | 1289 +++ + drivers/media/i2c/ov5647.c | 1343 +++- + drivers/media/i2c/ov7251.c | 15 +- + drivers/media/i2c/ov9281.c | 1294 +++ drivers/media/i2c/tc358743.c | 135 +- drivers/media/mc/mc-request.c | 35 + drivers/media/platform/Kconfig | 1 + drivers/media/platform/Makefile | 2 + drivers/media/platform/bcm2835/Kconfig | 21 + drivers/media/platform/bcm2835/Makefile | 3 + - .../media/platform/bcm2835/bcm2835-unicam.c | 2913 +++++++ + .../media/platform/bcm2835/bcm2835-unicam.c | 3434 ++++++++ .../media/platform/bcm2835/vc4-regs-unicam.h | 253 + drivers/media/spi/Kconfig | 1 + drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 4 + - drivers/media/v4l2-core/v4l2-ctrls.c | 11 + + drivers/media/v4l2-core/v4l2-ctrls.c | 12 + drivers/media/v4l2-core/v4l2-ioctl.c | 6 + drivers/media/v4l2-core/v4l2-mem2mem.c | 9 +- + drivers/media/v4l2-core/v4l2-subdev.c | 48 +- drivers/mfd/Kconfig | 8 + drivers/mfd/Makefile | 1 + drivers/mfd/bcm2835-pm.c | 11 + @@ -600,18 +617,21 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 + drivers/net/phy/broadcom.c | 37 +- drivers/net/phy/microchip.c | 27 + - drivers/net/phy/smsc.c | 4 +- + drivers/net/phy/smsc.c | 12 +- drivers/net/usb/Makefile | 2 +- - drivers/net/usb/lan78xx.c | 64 +- + drivers/net/usb/lan78xx.c | 65 +- drivers/net/usb/r8152.c | 3929 +++++++-- drivers/net/usb/r8153_ecm.c | 162 + drivers/net/usb/smsc95xx.c | 80 +- .../broadcom/brcm80211/brcmfmac/bus.h | 11 +- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 62 +- .../broadcom/brcm80211/brcmfmac/common.c | 14 +- + .../broadcom/brcm80211/brcmfmac/debug.h | 7 +- .../broadcom/brcm80211/brcmfmac/firmware.c | 23 +- + .../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 + + .../wireless/broadcom/brcm80211/brcmfmac/of.h | 7 + .../broadcom/brcm80211/brcmfmac/pcie.c | 7 +- - .../broadcom/brcm80211/brcmfmac/sdio.c | 19 +- + .../broadcom/brcm80211/brcmfmac/sdio.c | 64 +- .../broadcom/brcm80211/brcmfmac/usb.c | 7 +- drivers/nvmem/Kconfig | 8 + drivers/nvmem/Makefile | 2 + @@ -625,13 +645,13 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/perf/Kconfig | 8 + drivers/perf/Makefile | 1 + drivers/perf/raspberrypi_axi_monitor.c | 637 ++ - drivers/pinctrl/bcm/pinctrl-bcm2835.c | 43 +- + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 14 +- drivers/power/reset/gpio-poweroff.c | 20 +- drivers/power/supply/Kconfig | 6 + drivers/power/supply/Makefile | 1 + drivers/power/supply/rpi_poe_power.c | 227 + drivers/pps/clients/pps-gpio.c | 2 + - .../regulator/rpi-panel-attiny-regulator.c | 254 +- + .../regulator/rpi-panel-attiny-regulator.c | 297 +- drivers/rtc/rtc-pcf2123.c | 1 + drivers/rtc/rtc-pcf85063.c | 2 + drivers/rtc/rtc-pcf8523.c | 25 +- @@ -656,7 +676,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/staging/media/rpivid/rpivid_h265.c | 2688 +++++++ drivers/staging/media/rpivid/rpivid_hw.c | 366 + drivers/staging/media/rpivid/rpivid_hw.h | 303 + - drivers/staging/media/rpivid/rpivid_video.c | 708 ++ + drivers/staging/media/rpivid/rpivid_video.c | 707 ++ drivers/staging/media/rpivid/rpivid_video.h | 33 + drivers/staging/vc04_services/Kconfig | 4 + drivers/staging/vc04_services/Makefile | 3 + @@ -664,16 +684,17 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../vc04_services/bcm2835-audio/bcm2835.c | 130 +- .../vc04_services/bcm2835-audio/bcm2835.h | 4 +- .../bcm2835-camera/bcm2835-camera.c | 11 +- - .../vc04_services/bcm2835-camera/controls.c | 27 +- + .../bcm2835-camera/bcm2835-camera.h | 2 +- + .../vc04_services/bcm2835-camera/controls.c | 60 +- .../vc04_services/bcm2835-codec/Kconfig | 11 + .../vc04_services/bcm2835-codec/Makefile | 8 + .../staging/vc04_services/bcm2835-codec/TODO | 1 + - .../bcm2835-codec/bcm2835-v4l2-codec.c | 3646 +++++++++ + .../bcm2835-codec/bcm2835-v4l2-codec.c | 3684 +++++++++ .../staging/vc04_services/bcm2835-isp/Kconfig | 14 + .../vc04_services/bcm2835-isp/Makefile | 8 + .../bcm2835-isp/bcm2835-isp-ctrls.h | 72 + - .../bcm2835-isp/bcm2835-isp-fmts.h | 552 ++ - .../bcm2835-isp/bcm2835-v4l2-isp.c | 1762 ++++ + .../bcm2835-isp/bcm2835-isp-fmts.h | 553 ++ + .../bcm2835-isp/bcm2835-v4l2-isp.c | 1810 +++++ .../include/linux/broadcom/vc_sm_cma_ioctl.h | 114 + .../interface/vchiq_arm/vchiq_2835_arm.c | 142 +- .../interface/vchiq_arm/vchiq_arm.c | 36 + @@ -694,10 +715,10 @@ Subject: [PATCH] apply RPi patch of 5.10.74 .../vchiq-mmal/mmal-parameters.h | 251 +- .../vc04_services/vchiq-mmal/mmal-vchiq.c | 413 +- .../vc04_services/vchiq-mmal/mmal-vchiq.h | 5 + - drivers/thermal/broadcom/bcm2711_thermal.c | 2 +- + drivers/thermal/broadcom/bcm2711_thermal.c | 5 +- drivers/thermal/gov_step_wise.c | 33 +- drivers/tty/serial/8250/8250_bcm2835aux.c | 7 + - drivers/tty/serial/amba-pl011.c | 73 +- + drivers/tty/serial/amba-pl011.c | 75 +- drivers/tty/serial/sc16is7xx.c | 16 +- drivers/usb/Makefile | 1 + drivers/usb/core/generic.c | 1 + @@ -768,11 +789,11 @@ Subject: [PATCH] apply RPi patch of 5.10.74 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + .../usb/host/dwc_otg/test/test_mod_param.pl | 133 + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - drivers/usb/host/xhci-mem.c | 8 +- - drivers/usb/host/xhci-pci.c | 5 +- - drivers/usb/host/xhci-ring.c | 42 +- - drivers/usb/host/xhci.c | 103 + - drivers/usb/host/xhci.h | 6 +- + drivers/usb/host/xhci-mem.c | 67 +- + drivers/usb/host/xhci-pci.c | 3 + + drivers/usb/host/xhci-ring.c | 55 +- + drivers/usb/host/xhci.c | 104 +- + drivers/usb/host/xhci.h | 8 +- drivers/video/backlight/Kconfig | 7 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/rpi_backlight.c | 119 + @@ -788,7 +809,9 @@ Subject: [PATCH] apply RPi patch of 5.10.74 include/drm/drm_atomic.h | 20 + include/drm/drm_atomic_helper.h | 4 - include/drm/drm_connector.h | 4 + + include/drm/drm_edid.h | 4 +- include/drm/drm_modeset_helper_vtables.h | 56 +- + include/drm/drm_panel.h | 8 + include/drm/drm_probe_helper.h | 1 + include/drm/gud.h | 333 + include/dt-bindings/gpio/gpio-fsm.h | 21 + @@ -819,17 +842,16 @@ Subject: [PATCH] apply RPi patch of 5.10.74 include/uapi/drm/drm_mode.h | 1 + include/uapi/linux/bcm2835-isp.h | 347 + include/uapi/linux/fb.h | 12 + - include/uapi/linux/media-bus-format.h | 7 +- - include/uapi/linux/v4l2-controls.h | 5 + + include/uapi/linux/media-bus-format.h | 8 +- + include/uapi/linux/v4l2-controls.h | 6 + include/uapi/linux/videodev2.h | 13 + kernel/cgroup/cgroup.c | 38 + kernel/resource.c | 6 + mm/page_alloc.c | 2 - - mm/zswap.c | 53 +- + mm/zswap.c | 61 +- net/bluetooth/smp.c | 16 +- scripts/Makefile.dtbinst | 6 +- scripts/Makefile.lib | 19 + - scripts/gcc-plugin.sh | 1 + sound/core/pcm_iec958.c | 129 +- sound/soc/bcm/Kconfig | 298 + sound/soc/bcm/Makefile | 69 +- @@ -879,7 +901,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 sound/soc/soc-core.c | 14 +- sound/usb/quirks-table.h | 9 + sound/usb/quirks.c | 6 + - 875 files changed, 170418 insertions(+), 4553 deletions(-) + 897 files changed, 175467 insertions(+), 4749 deletions(-) create mode 100644 Documentation/admin-guide/media/bcm2835-isp.rst create mode 100644 Documentation/devicetree/bindings/clock/raspberrypi,firmware-clocks.yaml create mode 100644 Documentation/devicetree/bindings/hwmon/rpi-poe-fan.txt @@ -921,12 +943,14 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts create mode 100644 arch/arm/boot/dts/bcm2710-rpi-3-b.dts create mode 100644 arch/arm/boot/dts/bcm2710-rpi-cm3.dts + create mode 100644 arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts + create mode 100644 arch/arm/boot/dts/bcm2710-rpi-zero-2.dts create mode 100644 arch/arm/boot/dts/bcm2710.dtsi create mode 100644 arch/arm/boot/dts/bcm2711-rpi-400.dts create mode 100644 arch/arm/boot/dts/bcm2711-rpi-cm4.dts + create mode 100644 arch/arm/boot/dts/bcm2711-rpi-cm4s.dts create mode 100644 arch/arm/boot/dts/bcm2711-rpi.dtsi create mode 100644 arch/arm/boot/dts/bcm271x-rpi-bt.dtsi - create mode 100644 arch/arm/boot/dts/bcm283x-rpi-cam1-regulator.dtsi create mode 100644 arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi create mode 100644 arch/arm/boot/dts/bcm283x-rpi-csi1-2lane.dtsi create mode 100644 arch/arm/boot/dts/bcm283x-rpi-csi1-4lane.dtsi @@ -966,6 +990,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm/boot/dts/overlays/cap1106-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/chipdip-dac-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/cma-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/cutiepi-panel-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dht11-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts @@ -982,6 +1007,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/exc3000-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/fbtft-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/fsm-demo-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/ghost-amp-overlay.dts @@ -1129,6 +1155,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi-gpio40-45-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi0-0cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi0-1cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi0-2cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts @@ -1167,7 +1194,9 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts - create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dpi-at056tn53v1-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dpi-panel-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dpi.dtsi create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-lt070me05000-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-lt070me05000-v2-overlay.dts @@ -1176,6 +1205,7 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-vga666-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vga666-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vl805-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/w5500-overlay.dts @@ -1195,8 +1225,11 @@ Subject: [PATCH] apply RPi patch of 5.10.74 create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dts create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-cm3.dts + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2-w.dts + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2.dts create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4.dts + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4s.dts create mode 120000 arch/arm64/boot/dts/broadcom/bcm283x-rpi-csi1-2lane.dtsi create mode 120000 arch/arm64/boot/dts/broadcom/bcm283x-rpi-lan7515.dtsi create mode 120000 arch/arm64/boot/dts/overlays @@ -1801,10 +1834,19 @@ index d900cc57b4ec..4d8a6b615e5b 100644 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml -index edb53ab0d9eb..4d50b22554a4 100644 +index edb53ab0d9eb..f474cc0feed6 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml -@@ -147,6 +147,8 @@ properties: +@@ -133,6 +133,8 @@ properties: + - frida,frd350h54004 + # FriendlyELEC HD702E 800x1280 LCD panel + - friendlyarm,hd702e ++ # Geekworm MZP280 2.8" 480x640 LCD panel with capacitive touch ++ - geekworm,mzp280 + # GiantPlus GPG48273QS5 4.3" (480x272) WQVGA TFT LCD panel + - giantplus,gpg48273qs5 + # GiantPlus GPM940B0 3.0" QVGA TFT LCD panel +@@ -147,6 +149,8 @@ properties: - ivo,m133nwf4-r0 # Innolux AT043TN24 4.3" WQVGA TFT LCD panel - innolux,at043tn24 @@ -3251,7 +3293,7 @@ index 000000000000..f8d32547195b +zte ZTE Corp. +zyxel ZyXEL Communications Corp. diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml -index 2735be1a8470..0d306469abd0 100644 +index 2735be1a8470..e8a98ec7632d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -159,6 +159,8 @@ patternProperties: @@ -3263,6 +3305,15 @@ index 2735be1a8470..0d306469abd0 100644 "^boe,.*": description: BOE Technology Group Co., Ltd. "^bosch,.*": +@@ -399,6 +401,8 @@ patternProperties: + description: General Electric Company + "^geekbuying,.*": + description: GeekBuying ++ "^geekworm,.*": ++ description: Geekworm + "^gef,.*": + description: GE Fanuc Intelligent Platforms Embedded Systems, Inc. + "^GEFanuc,.*": diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt new file mode 100644 index 000000000000..5fa43e064307 @@ -3404,6 +3455,34 @@ index b864869b42bc..3163f501afb4 100644 ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` Specifies the decoding mode to use. Currently exposes slice-based and frame-based decoding but new modes might be added later on. +diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst +index 9457dc340c31..af8fa25026c0 100644 +--- a/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst ++++ b/Documentation/userspace-api/media/v4l/ext-ctrls-image-source.rst +@@ -58,3 +58,23 @@ Image Source Control IDs + The unit cell consists of the whole area of the pixel, sensitive and + non-sensitive. + This control is required for automatic calibration of sensors/cameras. ++ ++``V4L2_CID_NOTIFY_GAINS (integer array)`` ++ The sensor is notified what gains will be applied to the different ++ colour channels by subsequent processing (such as by an ISP). The ++ sensor is merely informed of these values in case it performs ++ processing that requires them, but it does not apply them itself to ++ the output pixels. ++ ++ Currently it is defined only for Bayer sensors, and is an array ++ control taking 4 gain values, being the gains for each of the ++ Bayer channels. The gains are always in the order B, Gb, Gr and R, ++ irrespective of the exact Bayer order of the sensor itself. ++ ++ The use of an array allows this control to be extended to sensors ++ with, for example, non-Bayer CFAs (colour filter arrays). ++ ++ The units for the gain values are linear, with the default value ++ representing a gain of exactly 1.0. For example, if this default value ++ is reported as being (say) 128, then a value of 192 would represent ++ a gain of exactly 1.5. diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst index fff25357fe86..c1dd92a2d617 100644 --- a/Documentation/userspace-api/media/v4l/meta-formats.rst @@ -3882,10 +3961,54 @@ index 000000000000..27fe14c9a9eb + + Y'\ :sub:`02low bits 5--4`\ (bits 1--0) diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst -index eff6727c69d3..8e0ae032411a 100644 +index eff6727c69d3..a62c416f1408 100644 --- a/Documentation/userspace-api/media/v4l/subdev-formats.rst +++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst -@@ -908,6 +908,43 @@ The following tables list existing packed RGB formats. +@@ -620,6 +620,43 @@ The following tables list existing packed RGB formats. + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` ++ * .. _MEDIA_BUS_FMT_RGB565_1X24_CPADHI: ++ ++ - MEDIA_BUS_FMT_RGB565_1X24_CPADHI ++ - 0x1020 ++ - ++ - ++ - ++ - ++ - ++ - ++ - ++ - ++ - ++ - 0 ++ - 0 ++ - 0 ++ - r\ :sub:`4` ++ - r\ :sub:`3` ++ - r\ :sub:`2` ++ - r\ :sub:`1` ++ - r\ :sub:`0` ++ - 0 ++ - 0 ++ - g\ :sub:`5` ++ - g\ :sub:`4` ++ - g\ :sub:`3` ++ - g\ :sub:`2` ++ - g\ :sub:`1` ++ - g\ :sub:`0` ++ - 0 ++ - 0 ++ - 0 ++ - b\ :sub:`4` ++ - b\ :sub:`3` ++ - b\ :sub:`2` ++ - b\ :sub:`1` ++ - b\ :sub:`0` + * .. _MEDIA-BUS-FMT-BGR565-2X8-BE: + + - MEDIA_BUS_FMT_BGR565_2X8_BE +@@ -908,6 +945,43 @@ The following tables list existing packed RGB formats. - g\ :sub:`5` - g\ :sub:`4` - g\ :sub:`3` @@ -3929,7 +4052,7 @@ index eff6727c69d3..8e0ae032411a 100644 * .. _MEDIA-BUS-FMT-RGB666-1X18: - MEDIA_BUS_FMT_RGB666_1X18 -@@ -982,6 +1019,43 @@ The following tables list existing packed RGB formats. +@@ -982,6 +1056,43 @@ The following tables list existing packed RGB formats. - g\ :sub:`2` - g\ :sub:`1` - g\ :sub:`0` @@ -3973,7 +4096,7 @@ index eff6727c69d3..8e0ae032411a 100644 * .. _MEDIA-BUS-FMT-RGB666-1X24_CPADHI: - MEDIA_BUS_FMT_RGB666_1X24_CPADHI -@@ -7899,3 +7973,36 @@ formats. +@@ -7899,3 +8010,36 @@ formats. - 0x5001 - Interleaved raw UYVY and JPEG image format with embedded meta-data used by Samsung S3C73MX camera sensors. @@ -4033,10 +4156,10 @@ index 4a05a105a9e6..ba3a5b599362 100644 pixfmt-nv16m pixfmt-nv24 diff --git a/MAINTAINERS b/MAINTAINERS -index 20ea04bb5542..93443e0ea919 100644 +index 34e5b245fc07..f57cac466bda 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -3417,6 +3417,29 @@ N: bcm113* +@@ -3427,6 +3427,29 @@ N: bcm113* N: bcm216* N: kona @@ -4066,7 +4189,7 @@ index 20ea04bb5542..93443e0ea919 100644 BROADCOM BCM47XX MIPS ARCHITECTURE M: Hauke Mehrtens M: Rafał Miłecki -@@ -5502,6 +5525,14 @@ S: Maintained +@@ -5522,6 +5545,14 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c @@ -4081,7 +4204,7 @@ index 20ea04bb5542..93443e0ea919 100644 DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS M: Hans de Goede S: Maintained -@@ -16369,6 +16400,23 @@ S: Maintained +@@ -16471,6 +16502,23 @@ S: Maintained T: git git://linuxtv.org/media_tree.git F: drivers/media/i2c/imx355.c @@ -4106,10 +4229,10 @@ index 20ea04bb5542..93443e0ea919 100644 M: Maxim Levitsky M: Alex Dubov diff --git a/Makefile b/Makefile -index fbd2136f7bf8..624cb8c91b19 100644 +index 4778c71a1e75..c688bd12b3a1 100644 --- a/Makefile +++ b/Makefile -@@ -1354,6 +1354,9 @@ ifneq ($(dtstree),) +@@ -1385,6 +1385,9 @@ ifneq ($(dtstree),) %.dtb: include/config/kernel.release scripts_dtc $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ @@ -4120,10 +4243,10 @@ index fbd2136f7bf8..624cb8c91b19 100644 dtbs: include/config/kernel.release scripts_dtc $(Q)$(MAKE) $(build)=$(dtstree) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index ce66ffd5a1bb..12cd8bf582e1 100644 +index d93f01dddc3f..432c4d76bb35 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -1,4 +1,21 @@ +@@ -1,4 +1,24 @@ # SPDX-License-Identifier: GPL-2.0 + +dtb-$(CONFIG_ARCH_BCM2835) += \ @@ -4133,6 +4256,8 @@ index ce66ffd5a1bb..12cd8bf582e1 100644 + bcm2708-rpi-cm.dtb \ + bcm2708-rpi-zero.dtb \ + bcm2708-rpi-zero-w.dtb \ ++ bcm2710-rpi-zero-2.dtb \ ++ bcm2710-rpi-zero-2-w.dtb \ + bcm2709-rpi-2-b.dtb \ + bcm2710-rpi-2-b.dtb \ + bcm2710-rpi-3-b.dtb \ @@ -4140,12 +4265,13 @@ index ce66ffd5a1bb..12cd8bf582e1 100644 + bcm2711-rpi-4-b.dtb \ + bcm2711-rpi-400.dtb \ + bcm2710-rpi-cm3.dtb \ -+ bcm2711-rpi-cm4.dtb ++ bcm2711-rpi-cm4.dtb \ ++ bcm2711-rpi-cm4s.dtb + dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -92,7 +109,6 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ +@@ -92,7 +112,6 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ bcm2837-rpi-3-b.dtb \ bcm2837-rpi-3-b-plus.dtb \ bcm2837-rpi-cm3-io3.dtb \ @@ -4153,7 +4279,7 @@ index ce66ffd5a1bb..12cd8bf582e1 100644 bcm2835-rpi-zero.dtb \ bcm2835-rpi-zero-w.dtb dtb-$(CONFIG_ARCH_BCM_5301X) += \ -@@ -1408,3 +1424,13 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ +@@ -1410,3 +1429,13 @@ dtb-$(CONFIG_ARCH_ASPEED) += \ aspeed-bmc-opp-zaius.dtb \ aspeed-bmc-portwell-neptune.dtb \ aspeed-bmc-quanta-q71l.dtb @@ -4169,10 +4295,10 @@ index ce66ffd5a1bb..12cd8bf582e1 100644 +endif diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts new file mode 100644 -index 000000000000..e42cba84ab0e +index 000000000000..a7d6427671b4 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,129 @@ +@@ -0,0 +1,131 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -4180,7 +4306,6 @@ index 000000000000..e42cba84ab0e +#include "bcm283x-rpi-smsc9514.dtsi" +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_28.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; @@ -4291,6 +4416,9 @@ index 000000000000..e42cba84ab0e + gpio = <&gpio 41 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -4304,17 +4432,16 @@ index 000000000000..e42cba84ab0e +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts b/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts new file mode 100644 -index 000000000000..4ea1e68f5e29 +index 000000000000..af1b477f7927 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts -@@ -0,0 +1,132 @@ +@@ -0,0 +1,134 @@ +/dts-v1/; + +#include "bcm2708.dtsi" +#include "bcm2708-rpi.dtsi" +#include "bcm283x-rpi-smsc9512.dtsi" +#include "bcm283x-rpi-csi1-2lane.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,model-b", "brcm,bcm2835"; @@ -4433,6 +4560,9 @@ index 000000000000..4ea1e68f5e29 + gpio = <&gpio 27 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -4442,10 +4572,10 @@ index 000000000000..4ea1e68f5e29 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts new file mode 100644 -index 000000000000..a152c1c8e648 +index 000000000000..a5316257a18b --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,119 @@ +@@ -0,0 +1,121 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -4453,7 +4583,6 @@ index 000000000000..a152c1c8e648 +#include "bcm283x-rpi-smsc9512.dtsi" +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_28.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,model-b", "brcm,bcm2835"; @@ -4558,6 +4687,9 @@ index 000000000000..a152c1c8e648 + gpio = <&gpio 21 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -4599,10 +4731,10 @@ index 000000000000..a18f80af97d3 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts new file mode 100644 -index 000000000000..f61e3418425a +index 000000000000..863bd207e323 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -0,0 +1,112 @@ +@@ -0,0 +1,106 @@ +/dts-v1/; + +#include "bcm2708-rpi-cm.dtsi" @@ -4613,21 +4745,15 @@ index 000000000000..f61e3418425a +/ { + compatible = "raspberrypi,compute-module", "brcm,bcm2835"; + model = "Raspberry Pi Compute Module"; ++}; + -+ cam1_reg: cam1_reg { -+ compatible = "regulator-fixed"; -+ regulator-name = "cam1-regulator"; -+ gpio = <&gpio 2 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ status = "disabled"; -+ }; -+ cam0_reg: cam0_reg { -+ compatible = "regulator-fixed"; -+ regulator-name = "cam0-regulator"; -+ gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ status = "disabled"; -+ }; ++&cam1_reg { ++ gpio = <&gpio 2 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++}; ++ ++cam0_reg: &cam0_regulator { ++ gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; +}; + +&uart0 { @@ -4717,10 +4843,10 @@ index 000000000000..f61e3418425a +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi new file mode 100644 -index 000000000000..d5572b2d2103 +index 000000000000..dd59f884d796 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi -@@ -0,0 +1,18 @@ +@@ -0,0 +1,22 @@ +#include "bcm2708.dtsi" +#include "bcm2708-rpi.dtsi" + @@ -4737,14 +4863,18 @@ index 000000000000..d5572b2d2103 + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; ++ cam0_reg = <&cam0_reg>,"status"; ++ cam0_reg_gpio = <&cam0_reg>,"gpios:4"; ++ cam1_reg = <&cam1_reg>,"status"; ++ cam1_reg_gpio = <&cam1_reg>,"gpios:4"; + }; +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts new file mode 100644 -index 000000000000..75a5b41514f9 +index 000000000000..e4c6c352f3aa --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts -@@ -0,0 +1,169 @@ +@@ -0,0 +1,178 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -4752,7 +4882,6 @@ index 000000000000..75a5b41514f9 +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_28.dtsi" +#include "bcm2708-rpi-bt.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,model-zero-w", "brcm,bcm2835"; @@ -4830,6 +4959,13 @@ index 000000000000..75a5b41514f9 + pinctrl-0 = <&sdio_pins>; + bus-width = <4>; + status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; +}; + +&uart0 { @@ -4907,6 +5043,9 @@ index 000000000000..75a5b41514f9 + gpio = <&gpio 44 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -4916,17 +5055,16 @@ index 000000000000..75a5b41514f9 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-zero.dts b/arch/arm/boot/dts/bcm2708-rpi-zero.dts new file mode 100644 -index 000000000000..84591bd7d423 +index 000000000000..19dae0d682ed --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts -@@ -0,0 +1,123 @@ +@@ -0,0 +1,125 @@ +/dts-v1/; + +#include "bcm2708.dtsi" +#include "bcm2708-rpi.dtsi" +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_28.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,model-zero", "brcm,bcm2835"; @@ -5036,6 +5174,9 @@ index 000000000000..84591bd7d423 + gpio = <&gpio 41 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -5105,10 +5246,10 @@ index 000000000000..36ec4989403f +}; diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 000000000000..e1381d2b3a2c +index 000000000000..4c80d15981fe --- /dev/null +++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,129 @@ +@@ -0,0 +1,131 @@ +/dts-v1/; + +#include "bcm2709.dtsi" @@ -5116,7 +5257,6 @@ index 000000000000..e1381d2b3a2c +#include "bcm283x-rpi-smsc9514.dtsi" +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_28.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,2-model-b", "brcm,bcm2836"; @@ -5227,6 +5367,9 @@ index 000000000000..e1381d2b3a2c + gpio = <&gpio 41 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -5440,10 +5583,10 @@ index 000000000000..57e7d5f60d3e +}; diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi new file mode 100644 -index 000000000000..badcf341ecd2 +index 000000000000..a5cabb5bc4a1 --- /dev/null +++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -0,0 +1,217 @@ +@@ -0,0 +1,272 @@ +/* Downstream bcm283x.dtsi diff */ +#include + @@ -5599,6 +5742,39 @@ index 000000000000..badcf341ecd2 + }; + }; + ++ cam1_reg: cam1_regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam1-reg"; ++ enable-active-high; ++ /* Needs to be enabled, as removing a regulator is very unsafe */ ++ status = "okay"; ++ }; ++ ++ cam1_clk: cam1_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_regulator: cam0_regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam0-reg"; ++ enable-active-high; ++ status = "disabled"; ++ }; ++ ++ cam0_clk: cam0_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam_dummy_reg: cam_dummy_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam-dummy-reg"; ++ status = "okay"; ++ }; ++ + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; @@ -5635,6 +5811,28 @@ index 000000000000..badcf341ecd2 + 20 21>; + brcm,function = ; + }; ++ dpi_16bit_gpio0: dpi_16bit_gpio0 { ++ brcm,pins = <0 1 2 3 4 5 6 7 8 9 10 11 ++ 12 13 14 15 16 17 18 19>; ++ brcm,function = ; ++ }; ++ dpi_16bit_gpio2: dpi_16bit_gpio2 { ++ brcm,pins = <2 3 4 5 6 7 8 9 10 11 ++ 12 13 14 15 16 17 18 19>; ++ brcm,function = ; ++ }; ++ dpi_16bit_cpadhi_gpio0: dpi_16bit_cpadhi_gpio0 { ++ brcm,pins = <0 1 2 3 4 5 6 7 8 ++ 12 13 14 15 16 17 ++ 20 21 22 23 24>; ++ brcm,function = ; ++ }; ++ dpi_16bit_cpadhi_gpio2: dpi_16bit_cpadhi_gpio2 { ++ brcm,pins = <2 3 4 5 6 7 8 ++ 12 13 14 15 16 17 ++ 20 21 22 23 24>; ++ brcm,function = ; ++ }; +}; + +&uart0 { @@ -5663,10 +5861,10 @@ index 000000000000..badcf341ecd2 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-2-b.dts b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts new file mode 100644 -index 000000000000..ae9db1b1be1b +index 000000000000..a8a18ef4d1bf --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts -@@ -0,0 +1,129 @@ +@@ -0,0 +1,131 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -5674,7 +5872,6 @@ index 000000000000..ae9db1b1be1b +#include "bcm283x-rpi-smsc9514.dtsi" +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_28.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,2-model-b-rev2", "brcm,bcm2837"; @@ -5785,6 +5982,9 @@ index 000000000000..ae9db1b1be1b + gpio = <&gpio 41 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -5798,10 +5998,10 @@ index 000000000000..ae9db1b1be1b +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts new file mode 100644 -index 000000000000..7e12c05cc28b +index 000000000000..93f9c8dddbca --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts -@@ -0,0 +1,201 @@ +@@ -0,0 +1,210 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -5810,7 +6010,6 @@ index 000000000000..7e12c05cc28b +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_44.dtsi" +#include "bcm271x-rpi-bt.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,3-model-b-plus", "brcm,bcm2837"; @@ -5888,6 +6087,13 @@ index 000000000000..7e12c05cc28b + pinctrl-0 = <&sdio_pins>; + bus-width = <4>; + status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; +}; + +&firmware { @@ -5985,6 +6191,9 @@ index 000000000000..7e12c05cc28b + gpio = <&expgpio 5 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -6005,10 +6214,10 @@ index 000000000000..7e12c05cc28b +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts new file mode 100644 -index 000000000000..d40722ddc286 +index 000000000000..bc5d086beb93 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -0,0 +1,203 @@ +@@ -0,0 +1,212 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -6017,7 +6226,6 @@ index 000000000000..d40722ddc286 +#include "bcm283x-rpi-csi1-2lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_44.dtsi" +#include "bcm271x-rpi-bt.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + compatible = "raspberrypi,3-model-b", "brcm,bcm2837"; @@ -6095,6 +6303,13 @@ index 000000000000..d40722ddc286 + pinctrl-0 = <&sdio_pins>; + bus-width = <4>; + status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; +}; + +&soc { @@ -6201,6 +6416,9 @@ index 000000000000..d40722ddc286 + gpio = <&expgpio 5 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -6214,10 +6432,10 @@ index 000000000000..d40722ddc286 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts new file mode 100644 -index 000000000000..c386a855cdc3 +index 000000000000..517ed47c257d --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -0,0 +1,148 @@ +@@ -0,0 +1,146 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -6228,21 +6446,15 @@ index 000000000000..c386a855cdc3 +/ { + compatible = "raspberrypi,3-compute-module", "brcm,bcm2837"; + model = "Raspberry Pi Compute Module 3"; ++}; + -+ cam1_reg: cam1_reg { -+ compatible = "regulator-fixed"; -+ regulator-name = "cam1-regulator"; -+ gpio = <&gpio 2 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ status = "disabled"; -+ }; -+ cam0_reg: cam0_reg { -+ compatible = "regulator-fixed"; -+ regulator-name = "cam0-regulator"; -+ gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ status = "disabled"; -+ }; ++&cam1_reg { ++ gpio = <&gpio 2 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++}; ++ ++cam0_reg: &cam0_regulator { ++ gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; +}; + +&uart0 { @@ -6364,141 +6576,371 @@ index 000000000000..c386a855cdc3 + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; ++ cam0_reg = <&cam0_reg>,"status"; ++ cam0_reg_gpio = <&cam0_reg>,"gpios:4"; ++ cam1_reg = <&cam1_reg>,"status"; ++ cam1_reg_gpio = <&cam1_reg>,"gpios:4"; + }; +}; -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi +diff --git a/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts b/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts new file mode 100644 -index 000000000000..e7e5c913f1d1 +index 000000000000..38629ebfa47f --- /dev/null -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -0,0 +1,25 @@ -+#include "bcm2837.dtsi" -+#include "bcm270x.dtsi" ++++ b/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts +@@ -0,0 +1,199 @@ ++/dts-v1/; + -+/ { -+ compatible = "brcm,bcm2837", "brcm,bcm2836"; ++#include "bcm2710.dtsi" ++#include "bcm2709-rpi.dtsi" ++#include "bcm283x-rpi-csi1-2lane.dtsi" ++#include "bcm283x-rpi-i2c0mux_0_44.dtsi" ++#include "bcm2708-rpi-bt.dtsi" + -+ arm-pmu { -+ compatible = "arm,cortex-a53-pmu", "arm,cortex-a7-pmu"; -+ }; ++/ { ++ compatible = "raspberrypi,model-zero-2-w", "brcm,bcm2837"; ++ model = "Raspberry Pi Zero 2 W"; + -+ soc { -+ /delete-node/ timer@7e003000; ++ chosen { ++ bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + }; + -+ __overrides__ { -+ arm_freq = <&cpu0>, "clock-frequency:0", -+ <&cpu1>, "clock-frequency:0", -+ <&cpu2>, "clock-frequency:0", -+ <&cpu3>, "clock-frequency:0"; ++ aliases { ++ serial0 = &uart1; ++ serial1 = &uart0; ++ mmc1 = &mmcnr; + }; +}; + -+&vc4 { -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts -index 5395e8c2484e..e0d1128c9439 100644 ---- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts -+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts -@@ -2,7 +2,6 @@ - /dts-v1/; - #include "bcm2711.dtsi" - #include "bcm2835-rpi.dtsi" --#include "bcm283x-rpi-usb-peripheral.dtsi" - - #include - -@@ -25,6 +24,7 @@ aliases { - emmc2bus = &emmc2bus; - ethernet0 = &genet; - pcie0 = &pcie0; -+ blconfig = &blconfig; - }; - - leds { -@@ -95,7 +95,7 @@ expgpio: gpio { - "VDD_SD_IO_SEL", - "CAM_GPIO", - "SD_PWR_ON", -- ""; -+ "SD_OC_N"; - status = "okay"; - }; - -@@ -216,6 +216,22 @@ &pwm1 { - status = "okay"; - }; - -+&rmem { -+ /* -+ * RPi4's co-processor will copy the board's bootloader configuration -+ * into memory for the OS to consume. It'll also update this node with -+ * its placement information. -+ */ -+ blconfig: nvram@0 { -+ compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x0 0x0 0x0>; -+ no-map; -+ status = "disabled"; ++&gpio { ++ spi0_pins: spi0_pins { ++ brcm,pins = <9 10 11>; ++ brcm,function = <4>; /* alt0 */ + }; -+}; + - /* SDHCI is used to control the SDIO for wireless */ - &sdhci { - #address-cells = <1>; -@@ -301,3 +317,309 @@ &vc4 { - &vec { - status = "disabled"; - }; ++ spi0_cs_pins: spi0_cs_pins { ++ brcm,pins = <8 7>; ++ brcm,function = <1>; /* output */ ++ }; + -+// ============================================= -+// Downstream rpi- changes ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; + -+#define BCM2711 ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; + -+#include "bcm270x.dtsi" -+#include "bcm271x-rpi-bt.dtsi" ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; + -+/ { -+ soc { -+ /delete-node/ pixelvalve@7e807000; -+ /delete-node/ hdmi@7e902000; ++ sdio_pins: sdio_pins { ++ brcm,pins = <34 35 36 37 38 39>; ++ brcm,function = <7>; // alt3 = SD1 ++ brcm,pull = <0 2 2 2 2 2>; + }; -+}; + -+#include "bcm2711-rpi.dtsi" -+#include "bcm283x-rpi-csi1-2lane.dtsi" -+#include "bcm283x-rpi-i2c0mux_0_44.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" ++ bt_pins: bt_pins { ++ brcm,pins = <43>; ++ brcm,function = <4>; /* alt0:GPCLK2 */ ++ brcm,pull = <0>; ++ }; + -+/ { -+ chosen { -+ bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ uart0_pins: uart0_pins { ++ brcm,pins = <30 31 32 33>; ++ brcm,function = <7>; /* alt3=UART0 */ ++ brcm,pull = <2 0 0 2>; /* up none none up */ + }; + -+ aliases { -+ serial0 = &uart1; -+ serial1 = &uart0; -+ mmc0 = &emmc2; -+ mmc1 = &mmcnr; -+ mmc2 = &sdhost; -+ i2c3 = &i2c3; -+ i2c4 = &i2c4; -+ i2c5 = &i2c5; -+ i2c6 = &i2c6; -+ i2c20 = &ddc0; -+ i2c21 = &ddc1; -+ spi3 = &spi3; -+ spi4 = &spi4; -+ spi5 = &spi5; -+ spi6 = &spi6; -+ /delete-property/ intc; ++ uart1_pins: uart1_pins { ++ brcm,pins; ++ brcm,function; ++ brcm,pull; + }; + -+ /delete-node/ wifi-pwrseq; ++ audio_pins: audio_pins { ++ brcm,pins = <>; ++ brcm,function = <>; ++ }; ++}; ++ ++&mmcnr { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio_pins>; ++ bus-width = <4>; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ ++ firmwares { ++ fw_43436p { ++ chipid = <43430>; ++ revmask = <4>; ++ fw_base = "brcm/brcmfmac43436-sdio"; ++ }; ++ fw_43436s { ++ chipid = <43430>; ++ revmask = <2>; ++ fw_base = "brcm/brcmfmac43436s-sdio"; ++ }; ++ }; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins &bt_pins>; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ ++ spidev0: spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++ ++ spidev1: spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++}; ++ ++&i2c0if { ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c2 { ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&leds { ++ act_led: led-act { ++ label = "led0"; ++ linux,default-trigger = "actpwr"; ++ gpios = <&gpio 29 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&hdmi { ++ hpd-gpios = <&gpio 28 GPIO_ACTIVE_LOW>; ++}; ++ ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++ brcm,disable-headphones = <1>; ++}; ++ ++&bt { ++ shutdown-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; ++}; ++ ++&minibt { ++ shutdown-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; ++}; ++ ++&cam1_reg { ++ gpio = <&gpio 40 GPIO_ACTIVE_HIGH>; ++}; ++ ++cam0_reg: &cam_dummy_reg { ++}; ++ ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm2710-rpi-zero-2.dts b/arch/arm/boot/dts/bcm2710-rpi-zero-2.dts +new file mode 100644 +index 000000000000..daa12bd30d6b +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2710-rpi-zero-2.dts +@@ -0,0 +1 @@ ++#include "bcm2710-rpi-zero-2-w.dts" +diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi +new file mode 100644 +index 000000000000..e7e5c913f1d1 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2710.dtsi +@@ -0,0 +1,25 @@ ++#include "bcm2837.dtsi" ++#include "bcm270x.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2837", "brcm,bcm2836"; ++ ++ arm-pmu { ++ compatible = "arm,cortex-a53-pmu", "arm,cortex-a7-pmu"; ++ }; ++ ++ soc { ++ /delete-node/ timer@7e003000; ++ }; ++ ++ __overrides__ { ++ arm_freq = <&cpu0>, "clock-frequency:0", ++ <&cpu1>, "clock-frequency:0", ++ <&cpu2>, "clock-frequency:0", ++ <&cpu3>, "clock-frequency:0"; ++ }; ++}; ++ ++&vc4 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +index 167538518a1e..fb44c89f3b0c 100644 +--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +@@ -2,7 +2,6 @@ + /dts-v1/; + #include "bcm2711.dtsi" + #include "bcm2835-rpi.dtsi" +-#include "bcm283x-rpi-usb-peripheral.dtsi" + + #include + +@@ -25,6 +24,7 @@ aliases { + emmc2bus = &emmc2bus; + ethernet0 = &genet; + pcie0 = &pcie0; ++ blconfig = &blconfig; + }; + + leds { +@@ -95,7 +95,7 @@ expgpio: gpio { + "VDD_SD_IO_SEL", + "CAM_GPIO", + "SD_PWR_ON", +- ""; ++ "SD_OC_N"; + status = "okay"; + }; + +@@ -181,12 +181,14 @@ &gpio { + &hdmi0 { + clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; + clock-names = "hdmi", "bvb", "audio", "cec"; ++ wifi-2.4ghz-coexistence; + status = "okay"; + }; + + &hdmi1 { + clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; + clock-names = "hdmi", "bvb", "audio", "cec"; ++ wifi-2.4ghz-coexistence; + status = "okay"; + }; + +@@ -216,6 +218,22 @@ &pwm1 { + status = "okay"; + }; + ++&rmem { ++ /* ++ * RPi4's co-processor will copy the board's bootloader configuration ++ * into memory for the OS to consume. It'll also update this node with ++ * its placement information. ++ */ ++ blconfig: nvram@0 { ++ compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x0 0x0>; ++ no-map; ++ status = "disabled"; ++ }; ++}; ++ + /* SDHCI is used to control the SDIO for wireless */ + &sdhci { + #address-cells = <1>; +@@ -302,3 +320,311 @@ &vc4 { + &vec { + status = "disabled"; + }; ++ ++// ============================================= ++// Downstream rpi- changes ++ ++#define BCM2711 ++ ++#include "bcm270x.dtsi" ++#include "bcm271x-rpi-bt.dtsi" ++ ++/ { ++ soc { ++ /delete-node/ pixelvalve@7e807000; ++ /delete-node/ hdmi@7e902000; ++ }; ++}; ++ ++#include "bcm2711-rpi.dtsi" ++#include "bcm283x-rpi-csi1-2lane.dtsi" ++#include "bcm283x-rpi-i2c0mux_0_44.dtsi" ++ ++/ { ++ chosen { ++ bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ }; ++ ++ aliases { ++ serial0 = &uart1; ++ serial1 = &uart0; ++ mmc0 = &emmc2; ++ mmc1 = &mmcnr; ++ mmc2 = &sdhost; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ i2c20 = &ddc0; ++ i2c21 = &ddc1; ++ spi3 = &spi3; ++ spi4 = &spi4; ++ spi5 = &spi5; ++ spi6 = &spi6; ++ /delete-property/ intc; ++ }; ++ ++ /delete-node/ wifi-pwrseq; +}; + +&mmcnr { @@ -6741,6 +7183,9 @@ index 5395e8c2484e..e0d1128c9439 100644 + gpio = <&expgpio 5 GPIO_ACTIVE_HIGH>; +}; + ++cam0_reg: &cam_dummy_reg { ++}; ++ +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; @@ -6761,10 +7206,10 @@ index 5395e8c2484e..e0d1128c9439 100644 +}; diff --git a/arch/arm/boot/dts/bcm2711-rpi-400.dts b/arch/arm/boot/dts/bcm2711-rpi-400.dts new file mode 100644 -index 000000000000..c25a97465d2b +index 000000000000..ec0c75810754 --- /dev/null +++ b/arch/arm/boot/dts/bcm2711-rpi-400.dts -@@ -0,0 +1,636 @@ +@@ -0,0 +1,637 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +#include "bcm2711.dtsi" @@ -6860,9 +7305,9 @@ index 000000000000..c25a97465d2b + "PWR_LED_OFF", + "GLOBAL_RESET", + "VDD_SD_IO_SEL", -+ "CAM_GPIO", ++ "GLOBAL_SHUTDOWN", + "SD_PWR_ON", -+ "SD_OC_N"; ++ "SHUTDOWN_REQUEST"; + status = "okay"; + }; + @@ -7040,15 +7485,16 @@ index 000000000000..c25a97465d2b +}; + +&pcie0 { -+ pci@1,0 { ++ pci@0,0 { ++ device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + reg = <0 0 0 0 0>; + -+ usb@1,0 { -+ reg = <0x10000 0 0 0 0>; ++ usb@0,0 { ++ reg = <0 0 0 0 0>; + resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>; + }; + }; @@ -7403,17 +7849,15 @@ index 000000000000..c25a97465d2b +}; diff --git a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts new file mode 100644 -index 000000000000..1dcbb2173f5d +index 000000000000..5dbd1b77260b --- /dev/null +++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts -@@ -0,0 +1,659 @@ +@@ -0,0 +1,652 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +#include "bcm2711.dtsi" +#include "bcm2835-rpi.dtsi" + -+#include -+ +/ { + compatible = "raspberrypi,4-compute-module", "brcm,bcm2711"; + model = "Raspberry Pi Compute Module 4"; @@ -7695,17 +8139,13 @@ index 000000000000..1dcbb2173f5d +}; + +&pcie0 { -+ pci@1,0 { ++ pci@0,0 { ++ device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + reg = <0 0 0 0 0>; -+ -+ usb@1,0 { -+ reg = <0x10000 0 0 0 0>; -+ resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>; -+ }; + }; +}; + @@ -7761,7 +8201,6 @@ index 000000000000..1dcbb2173f5d +#include "bcm283x-rpi-csi0-2lane.dtsi" +#include "bcm283x-rpi-csi1-4lane.dtsi" +#include "bcm283x-rpi-i2c0mux_0_44.dtsi" -+#include "bcm283x-rpi-cam1-regulator.dtsi" + +/ { + chosen { @@ -8066,6 +8505,489 @@ index 000000000000..1dcbb2173f5d + <&spi0>, "dmas:8=", <&dma40>; + }; +}; +diff --git a/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts b/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts +new file mode 100644 +index 000000000000..0346d731dd0e +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts +@@ -0,0 +1,477 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/dts-v1/; ++#include "bcm2711.dtsi" ++#include "bcm2835-rpi.dtsi" ++ ++#include ++ ++/ { ++ compatible = "raspberrypi,4-compute-module-s", "brcm,bcm2711"; ++ model = "Raspberry Pi Compute Module 4S"; ++ ++ chosen { ++ /* 8250 auxiliary UART instead of pl011 */ ++ stdout-path = "serial1:115200n8"; ++ }; ++ ++ /* Will be filled by the bootloader */ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0 0 0>; ++ }; ++ ++ aliases { ++ emmc2bus = &emmc2bus; ++ blconfig = &blconfig; ++ }; ++ ++ leds { ++ led-act { ++ gpios = <&virtgpio 0 0>; ++ }; ++ }; ++}; ++ ++&ddc0 { ++ status = "okay"; ++}; ++ ++&firmware { ++ firmware_clocks: clocks { ++ compatible = "raspberrypi,firmware-clocks"; ++ #clock-cells = <1>; ++ }; ++ ++ reset: reset { ++ compatible = "raspberrypi,firmware-reset"; ++ #reset-cells = <1>; ++ }; ++}; ++ ++&gpio { ++ /* ++ * Parts taken from rpi_SCH_4b_4p0_reduced.pdf and ++ * the official GPU firmware DT blob. ++ * ++ * Legend: ++ * "FOO" = GPIO line named "FOO" on the schematic ++ * "FOO_N" = GPIO line named "FOO" on schematic, active low ++ */ ++ gpio-line-names = "ID_SDA", ++ "ID_SCL", ++ "SDA1", ++ "SCL1", ++ "GPIO_GCLK", ++ "GPIO5", ++ "GPIO6", ++ "SPI_CE1_N", ++ "SPI_CE0_N", ++ "SPI_MISO", ++ "SPI_MOSI", ++ "SPI_SCLK", ++ "GPIO12", ++ "GPIO13", ++ /* Serial port */ ++ "TXD1", ++ "RXD1", ++ "GPIO16", ++ "GPIO17", ++ "GPIO18", ++ "GPIO19", ++ "GPIO20", ++ "GPIO21", ++ "GPIO22", ++ "GPIO23", ++ "GPIO24", ++ "GPIO25", ++ "GPIO26", ++ "GPIO27", ++ "GPIO28", ++ "GPIO29", ++ "GPIO30", ++ "GPIO31", ++ "GPIO32", ++ "GPIO33", ++ "GPIO34", ++ "GPIO35", ++ "GPIO36", ++ "GPIO37", ++ "GPIO38", ++ "GPIO39", ++ "PWM0_MISO", ++ "PWM1_MOSI", ++ "GPIO42", ++ "GPIO43", ++ "GPIO44", ++ "GPIO45"; ++}; ++ ++&hdmi0 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ wifi-2.4ghz-coexistence; ++ status = "okay"; ++}; ++ ++ ++&hvs { ++ clocks = <&firmware_clocks 4>; ++}; ++ ++&pixelvalve0 { ++ status = "okay"; ++}; ++ ++&pixelvalve1 { ++ status = "okay"; ++}; ++ ++&pixelvalve2 { ++ status = "okay"; ++}; ++ ++&pixelvalve4 { ++ status = "okay"; ++}; ++ ++&pwm1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>; ++ status = "okay"; ++}; ++ ++&rmem { ++ /* ++ * RPi4's co-processor will copy the board's bootloader configuration ++ * into memory for the OS to consume. It'll also update this node with ++ * its placement information. ++ */ ++ blconfig: nvram@0 { ++ compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x0 0x0>; ++ no-map; ++ status = "disabled"; ++ }; ++}; ++ ++/* EMMC2 is used to drive the EMMC card */ ++&emmc2 { ++ bus-width = <8>; ++ broken-cd; ++ status = "okay"; ++}; ++ ++&pcie0 { ++ status = "disabled"; ++}; ++ ++&vchiq { ++ interrupts = ; ++}; ++ ++&vc4 { ++ status = "okay"; ++}; ++ ++&vec { ++ status = "disabled"; ++}; ++ ++// ============================================= ++// Downstream rpi- changes ++ ++#define BCM2711 ++ ++#include "bcm270x.dtsi" ++ ++/ { ++ soc { ++ /delete-node/ pixelvalve@7e807000; ++ /delete-node/ hdmi@7e902000; ++ ++ virtgpio: virtgpio { ++ compatible = "brcm,bcm2835-virtgpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; ++ }; ++}; ++ ++#include "bcm2711-rpi.dtsi" ++#include "bcm283x-rpi-csi0-2lane.dtsi" ++#include "bcm283x-rpi-csi1-4lane.dtsi" ++#include "bcm283x-rpi-i2c0mux_0_28.dtsi" ++ ++/ { ++ chosen { ++ bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ }; ++ ++ aliases { ++ serial0 = &uart0; ++ mmc0 = &emmc2; ++ mmc1 = &mmcnr; ++ mmc2 = &sdhost; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ spi3 = &spi3; ++ spi4 = &spi4; ++ spi5 = &spi5; ++ spi6 = &spi6; ++ /delete-property/ intc; ++ }; ++ ++ /delete-node/ wifi-pwrseq; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ ++ spidev0: spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++ ++ spidev1: spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++}; ++ ++&gpio { ++ spi0_pins: spi0_pins { ++ brcm,pins = <9 10 11>; ++ brcm,function = ; ++ }; ++ ++ spi0_cs_pins: spi0_cs_pins { ++ brcm,pins = <8 7>; ++ brcm,function = ; ++ }; ++ ++ spi3_pins: spi3_pins { ++ brcm,pins = <1 2 3>; ++ brcm,function = ; ++ }; ++ ++ spi3_cs_pins: spi3_cs_pins { ++ brcm,pins = <0 24>; ++ brcm,function = ; ++ }; ++ ++ spi4_pins: spi4_pins { ++ brcm,pins = <5 6 7>; ++ brcm,function = ; ++ }; ++ ++ spi4_cs_pins: spi4_cs_pins { ++ brcm,pins = <4 25>; ++ brcm,function = ; ++ }; ++ ++ spi5_pins: spi5_pins { ++ brcm,pins = <13 14 15>; ++ brcm,function = ; ++ }; ++ ++ spi5_cs_pins: spi5_cs_pins { ++ brcm,pins = <12 26>; ++ brcm,function = ; ++ }; ++ ++ spi6_pins: spi6_pins { ++ brcm,pins = <19 20 21>; ++ brcm,function = ; ++ }; ++ ++ spi6_cs_pins: spi6_cs_pins { ++ brcm,pins = <18 27>; ++ brcm,function = ; ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = ; ++ brcm,pull = ; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = ; ++ brcm,pull = ; ++ }; ++ ++ i2c3_pins: i2c3 { ++ brcm,pins = <4 5>; ++ brcm,function = ; ++ brcm,pull = ; ++ }; ++ ++ i2c4_pins: i2c4 { ++ brcm,pins = <8 9>; ++ brcm,function = ; ++ brcm,pull = ; ++ }; ++ ++ i2c5_pins: i2c5 { ++ brcm,pins = <12 13>; ++ brcm,function = ; ++ brcm,pull = ; ++ }; ++ ++ i2c6_pins: i2c6 { ++ brcm,pins = <22 23>; ++ brcm,function = ; ++ brcm,pull = ; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = ; ++ }; ++ ++ sdio_pins: sdio_pins { ++ brcm,pins = <34 35 36 37 38 39>; ++ brcm,function = ; // alt3 = SD1 ++ brcm,pull = <0 2 2 2 2 2>; ++ }; ++ ++ uart0_pins: uart0_pins { ++ brcm,pins; ++ brcm,function; ++ brcm,pull; ++ }; ++ ++ uart2_pins: uart2_pins { ++ brcm,pins = <0 1>; ++ brcm,function = ; ++ brcm,pull = <0 2>; ++ }; ++ ++ uart3_pins: uart3_pins { ++ brcm,pins = <4 5>; ++ brcm,function = ; ++ brcm,pull = <0 2>; ++ }; ++ ++ uart4_pins: uart4_pins { ++ brcm,pins = <8 9>; ++ brcm,function = ; ++ brcm,pull = <0 2>; ++ }; ++ ++ uart5_pins: uart5_pins { ++ brcm,pins = <12 13>; ++ brcm,function = ; ++ brcm,pull = <0 2>; ++ }; ++}; ++ ++&i2c0if { ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++// ============================================= ++// Board specific stuff here ++ ++/* Enable USB in OTG-aware mode */ ++&usb { ++ compatible = "brcm,bcm2835-usb"; ++ dr_mode = "otg"; ++ g-np-tx-fifo-size = <32>; ++ g-rx-fifo-size = <558>; ++ g-tx-fifo-size = <512 512 512 512 512 256 256>; ++ status = "okay"; ++}; ++ ++&sdhost { ++ status = "disabled"; ++}; ++ ++&gpio { ++ audio_pins: audio_pins { ++ brcm,pins = <>; ++ brcm,function = <>; ++ }; ++}; ++ ++/* Permanently disable HDMI1 */ ++&hdmi1 { ++ compatible = "disabled"; ++}; ++ ++/* Permanently disable DDC1 */ ++&ddc1 { ++ compatible = "disabled"; ++}; ++ ++&leds { ++ act_led: led-act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&virtgpio 0 0>; ++ }; ++}; ++ ++&pwm1 { ++ status = "disabled"; ++}; ++ ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++ brcm,disable-headphones = <1>; ++}; ++ ++&cam1_reg { ++ gpio = <&gpio 2 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++}; ++ ++cam0_reg: &cam0_regulator { ++ gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; ++ status = "disabled"; ++}; ++ ++/ { ++ __overrides__ { ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ sd_poll_once = <&emmc2>, "non-removable?"; ++ spi_dma4 = <&spi0>, "dmas:0=", <&dma40>, ++ <&spi0>, "dmas:8=", <&dma40>; ++ }; ++}; diff --git a/arch/arm/boot/dts/bcm2711-rpi.dtsi b/arch/arm/boot/dts/bcm2711-rpi.dtsi new file mode 100644 index 000000000000..ebf73b789b4a @@ -8278,17 +9200,17 @@ index 000000000000..ebf73b789b4a + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi -index 3d040f6e2a20..2933cf91c27d 100644 +index b50229c3102f..f8c327b3c660 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi -@@ -300,6 +300,14 @@ pixelvalve3: pixelvalve@7ec12000 { +@@ -301,6 +301,14 @@ pixelvalve3: pixelvalve@7ec12000 { status = "disabled"; }; + vec: vec@7ec13000 { + compatible = "brcm,bcm2711-vec"; + reg = <0x7ec13000 0x1000>; -+ clocks = <&clocks BCM2835_CLOCK_VEC>; ++ clocks = <&firmware_clocks 15>; + interrupts = ; + status = "disabled"; + }; @@ -8296,14 +9218,14 @@ index 3d040f6e2a20..2933cf91c27d 100644 dvp: clock@7ef00000 { compatible = "brcm,brcm2711-dvp"; reg = <0x7ef00000 0x10>; -@@ -308,6 +316,15 @@ dvp: clock@7ef00000 { +@@ -309,6 +317,15 @@ dvp: clock@7ef00000 { #reset-cells = <1>; }; + aon_intr: interrupt-controller@7ef00100 { + compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; + reg = <0x7ef00100 0x30>; -+ interrupts = ; ++ interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + status = "disabled"; @@ -8312,7 +9234,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 hdmi0: hdmi@7ef00700 { compatible = "brcm,bcm2711-hdmi0"; reg = <0x7ef00700 0x300>, -@@ -318,7 +335,8 @@ hdmi0: hdmi@7ef00700 { +@@ -319,7 +336,8 @@ hdmi0: hdmi@7ef00700 { <0x7ef01f00 0x400>, <0x7ef00200 0x80>, <0x7ef04300 0x100>, @@ -8322,7 +9244,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 reg-names = "hdmi", "dvp", "phy", -@@ -327,11 +345,21 @@ hdmi0: hdmi@7ef00700 { +@@ -328,11 +346,21 @@ hdmi0: hdmi@7ef00700 { "metadata", "csc", "cec", @@ -8346,7 +9268,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 dma-names = "audio-rx"; status = "disabled"; }; -@@ -354,7 +382,8 @@ hdmi1: hdmi@7ef05700 { +@@ -355,7 +383,8 @@ hdmi1: hdmi@7ef05700 { <0x7ef06f00 0x400>, <0x7ef00280 0x80>, <0x7ef09300 0x100>, @@ -8356,7 +9278,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 reg-names = "hdmi", "dvp", "phy", -@@ -363,11 +392,21 @@ hdmi1: hdmi@7ef05700 { +@@ -364,11 +393,21 @@ hdmi1: hdmi@7ef05700 { "metadata", "csc", "cec", @@ -8372,7 +9294,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 resets = <&dvp 1>; - dmas = <&dma 17>; + interrupt-parent = <&aon_intr>; -+ interrupts = <8>, <7>, <6>, ++ interrupts = <8>, <7>, <6>, // This is correct + <9>, <10>, <11>; + interrupt-names = "cec-tx", "cec-rx", "cec-low", + "wakeup", "hpd-connected", "hpd-removed"; @@ -8380,7 +9302,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 dma-names = "audio-rx"; status = "disabled"; }; -@@ -468,14 +507,14 @@ cpu3: cpu@3 { +@@ -519,14 +558,14 @@ l2: l2-cache0 { scb { compatible = "simple-bus"; #address-cells = <2>; @@ -8399,7 +9321,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 device_type = "pci"; #address-cells = <3>; #interrupt-cells = <1>; -@@ -489,8 +528,8 @@ pcie0: pcie@7d500000 { +@@ -546,8 +585,8 @@ IRQ_TYPE_LEVEL_HIGH>, msi-controller; msi-parent = <&pcie0>; @@ -8410,7 +9332,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 /* * The wrapper around the PCIe block has a bug * preventing it from accessing beyond the first 3GB of -@@ -503,7 +542,7 @@ pcie0: pcie@7d500000 { +@@ -560,7 +599,7 @@ IRQ_TYPE_LEVEL_HIGH>, genet: ethernet@7d580000 { compatible = "brcm,bcm2711-genet-v5"; @@ -8419,7 +9341,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 #address-cells = <0x1>; #size-cells = <0x1>; interrupts = , -@@ -540,6 +579,7 @@ &dsi0 { +@@ -597,6 +636,7 @@ &dsi0 { &dsi1 { interrupts = ; @@ -8427,7 +9349,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 }; &gpio { -@@ -1010,7 +1050,7 @@ &cma { +@@ -1069,7 +1109,7 @@ &cma { alloc-ranges = <0x0 0x00000000 0x40000000>; }; @@ -8436,7 +9358,7 @@ index 3d040f6e2a20..2933cf91c27d 100644 compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; interrupts = ; }; -@@ -1066,7 +1106,3 @@ &uart1 { +@@ -1125,7 +1165,3 @@ &uart1 { &usb { interrupts = ; }; @@ -8477,7 +9399,7 @@ index 000000000000..6b9b79f74cf3 + }; +}; diff --git a/arch/arm/boot/dts/bcm2835-common.dtsi b/arch/arm/boot/dts/bcm2835-common.dtsi -index 4119271c979d..06d8c3882cb7 100644 +index 4119271c979d..7f46a6ec512c 100644 --- a/arch/arm/boot/dts/bcm2835-common.dtsi +++ b/arch/arm/boot/dts/bcm2835-common.dtsi @@ -106,6 +106,14 @@ i2c2: i2c@7e805000 { @@ -8487,7 +9409,7 @@ index 4119271c979d..06d8c3882cb7 100644 + vec: vec@7e806000 { + compatible = "brcm,bcm2835-vec"; + reg = <0x7e806000 0x1000>; -+ clocks = <&clocks BCM2835_CLOCK_VEC>; ++ clocks = <&firmware_clocks 15>; + interrupts = <2 27>; + status = "disabled"; + }; @@ -8503,7 +9425,8 @@ index 4119271c979d..06d8c3882cb7 100644 + "hd"; interrupts = <2 8>, <2 9>; ddc = <&i2c2>; - clocks = <&clocks BCM2835_PLLH_PIX>, +- clocks = <&clocks BCM2835_PLLH_PIX>, ++ clocks = <&firmware_clocks 9>, <&clocks BCM2835_CLOCK_HSM>; clock-names = "pixel", "hdmi"; - dmas = <&dma 17>; @@ -8568,10 +9491,10 @@ index a23c25c00eea..547c88a3ae9f 100644 + pinctrl-1 = <&i2c0_gpio0>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts -index 1b63d6b19750..073fc99ef8a2 100644 +index 25d87212cefd..c9f3c4558442 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-b.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts -@@ -116,3 +116,10 @@ &uart0 { +@@ -115,3 +115,10 @@ &uart0 { pinctrl-0 = <&uart0_gpio14>; status = "okay"; }; @@ -8596,10 +9519,10 @@ index a75c882e6575..95564c93a645 100644 + pinctrl-1 = <&i2c0_gpio28>; +}; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts -index 33b2b77aa47d..3ea5c7e6be54 100644 +index 00582eb2c12e..7d3273496186 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts -@@ -149,3 +149,8 @@ &uart1 { +@@ -151,3 +151,8 @@ &uart1 { pinctrl-0 = <&uart1_gpio14>; status = "okay"; }; @@ -8709,7 +9632,7 @@ index 77099a7871b0..9529c0475673 100644 + pinctrl-1 = <&i2c0_gpio44>; +}; diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts -index 61010266ca9a..40cb269aed0f 100644 +index 90472e76a313..23fd63be2d4b 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts @@ -181,3 +181,8 @@ &uart1 { @@ -8735,7 +9658,7 @@ index dd4a48604097..8f16b6b3fe08 100644 + pinctrl-1 = <&i2c0_gpio44>; +}; diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts -index 588d9411ceb6..dde209ade51b 100644 +index 3dfce4312dfc..f0a7ef168fa7 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts @@ -94,3 +94,8 @@ &uart0 { @@ -8747,22 +9670,6 @@ index 588d9411ceb6..dde209ade51b 100644 +&i2c0mux { + pinctrl-1 = <&i2c0_gpio28>; +}; -diff --git a/arch/arm/boot/dts/bcm283x-rpi-cam1-regulator.dtsi b/arch/arm/boot/dts/bcm283x-rpi-cam1-regulator.dtsi -new file mode 100644 -index 000000000000..55237d03ed94 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm283x-rpi-cam1-regulator.dtsi -@@ -0,0 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+/ { -+ cam1_reg: cam1_reg { -+ compatible = "regulator-fixed"; -+ regulator-name = "cam1-reg"; -+ enable-active-high; -+ status = "disabled"; -+ }; -+}; diff --git a/arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi b/arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi new file mode 100644 index 000000000000..6e4ce8622b47 @@ -8827,10 +9734,10 @@ index 0ff0e9e25327..000000000000 - g-tx-fifo-size = <256 256 512 512 512 768 768>; -}; diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi -index 0f3be55201a5..06d04cde52b9 100644 +index ffdf7c4fba46..62d7ee513549 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi -@@ -334,7 +334,7 @@ spi: spi@7e204000 { +@@ -336,7 +336,7 @@ spi: spi@7e204000 { status = "disabled"; }; @@ -8839,7 +9746,7 @@ index 0f3be55201a5..06d04cde52b9 100644 compatible = "brcm,bcm2835-i2c"; reg = <0x7e205000 0x200>; interrupts = <2 21>; -@@ -344,6 +344,30 @@ i2c0: i2c@7e205000 { +@@ -346,6 +346,30 @@ i2c0: i2c@7e205000 { status = "disabled"; }; @@ -8870,7 +9777,7 @@ index 0f3be55201a5..06d04cde52b9 100644 dpi: dpi@7e208000 { compatible = "brcm,bcm2835-dpi"; reg = <0x7e208000 0x8c>; -@@ -464,14 +488,6 @@ i2c1: i2c@7e804000 { +@@ -466,14 +490,6 @@ i2c1: i2c@7e804000 { status = "disabled"; }; @@ -8887,10 +9794,10 @@ index 0f3be55201a5..06d04cde52b9 100644 reg = <0x7e980000 0x10000>; diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile new file mode 100644 -index 000000000000..b36c618b01d0 +index 000000000000..6fcacdccb608 --- /dev/null +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,252 @@ +@@ -0,0 +1,257 @@ +# Overlays for the Raspberry Pi platform + +dtb-$(CONFIG_ARCH_BCM2835) += overlay_map.dtb @@ -8927,6 +9834,7 @@ index 000000000000..b36c618b01d0 + cap1106.dtbo \ + chipdip-dac.dtbo \ + cma.dtbo \ ++ cutiepi-panel.dtbo \ + dht11.dtbo \ + dionaudio-loco.dtbo \ + dionaudio-loco-v2.dtbo \ @@ -8942,6 +9850,7 @@ index 000000000000..b36c618b01d0 + enc28j60.dtbo \ + enc28j60-spi2.dtbo \ + exc3000.dtbo \ ++ fbtft.dtbo \ + fe-pi-audio.dtbo \ + fsm-demo.dtbo \ + ghost-amp.dtbo \ @@ -9085,6 +9994,7 @@ index 000000000000..b36c618b01d0 + spi-gpio35-39.dtbo \ + spi-gpio40-45.dtbo \ + spi-rtc.dtbo \ ++ spi0-0cs.dtbo \ + spi0-1cs.dtbo \ + spi0-2cs.dtbo \ + spi1-1cs.dtbo \ @@ -9123,7 +10033,8 @@ index 000000000000..b36c618b01d0 + upstream-pi4.dtbo \ + vc4-fkms-v3d.dtbo \ + vc4-fkms-v3d-pi4.dtbo \ -+ vc4-kms-dpi-at056tn53v1.dtbo \ ++ vc4-kms-dpi-generic.dtbo \ ++ vc4-kms-dpi-panel.dtbo \ + vc4-kms-dsi-7inch.dtbo \ + vc4-kms-dsi-lt070me05000.dtbo \ + vc4-kms-dsi-lt070me05000-v2.dtbo \ @@ -9132,6 +10043,7 @@ index 000000000000..b36c618b01d0 + vc4-kms-v3d-pi4.dtbo \ + vc4-kms-vga666.dtbo \ + vga666.dtbo \ ++ vl805.dtbo \ + w1-gpio.dtbo \ + w1-gpio-pullup.dtbo \ + w5500.dtbo \ @@ -9145,10 +10057,10 @@ index 000000000000..b36c618b01d0 +clean-files := *.dtbo diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README new file mode 100644 -index 000000000000..5064d8eb2040 +index 000000000000..3a0961540427 --- /dev/null +++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,3576 @@ +@@ -0,0 +1,3861 @@ +Introduction +============ + @@ -9295,6 +10207,16 @@ index 000000000000..5064d8eb2040 + See /sys/kernel/debug/raspberrypi_axi_monitor + for the results. + ++ cam0_reg Enables CAM 0 regulator. CM1 & 3 only. ++ ++ cam0_reg_gpio Set GPIO for CAM 0 regulator. Default 30. ++ CM1 & 3 only. ++ ++ cam1_reg Enables CAM 1 regulator. CM1 & 3 only. ++ ++ cam1_reg_gpio Set GPIO for CAM 1 regulator. Default 2. ++ CM1 & 3 only. ++ + eee Enable Energy Efficient Ethernet support for + compatible devices (default "on"). See also + "tx_lpi_timer". Pi3B+ only. @@ -9567,6 +10489,8 @@ index 000000000000..5064d8eb2040 + variants. +Load: dtoverlay=adv7282m,= +Params: addr Overrides the I2C address (default 0x21) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default off) + + +Name: adv728x-m @@ -9577,6 +10501,8 @@ index 000000000000..5064d8eb2040 + adv7280m Select ADV7280-M. + adv7281m Select ADV7281-M. + adv7281ma Select ADV7281-MA. ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default off) + + +Name: akkordion-iqdacplus @@ -9816,6 +10742,12 @@ index 000000000000..5064d8eb2040 + cma-default Use upstream's default value + + ++Name: cutiepi-panel ++Info: 8" TFT LCD display and touch panel used by cutiepi.io ++Load: dtoverlay=cutiepi-panel ++Params: ++ ++ +Name: dht11 +Info: Overlay for the DHT11/DHT21/DHT22 humidity/temperature sensors + Also sometimes found with the part number(s) AM230x. @@ -10004,6 +10936,130 @@ index 000000000000..5064d8eb2040 + swapxy Touchscreen swapped x y axis + + ++Name: fbtft ++Info: Overlay for SPI-connected displays using the fbtft drivers. ++ ++ This overlay seeks to replace the functionality provided by fbtft_device ++ which is now gone from the kernel. ++ ++ Most displays from fbtft_device have been ported over. ++ Example: ++ dtoverlay=fbtft,spi0-0,rpi-display,reset_pin=23,dc_pin=24,led_pin=18,rotate=270 ++ ++ It is also possible to specify the controller (this will use the default ++ init sequence in the driver). ++ Example: ++ dtoverlay=fbtft,spi0-0,ili9341,bgr,reset_pin=23,dc_pin=24,led_pin=18,rotate=270 ++ ++ For devices on spi1 or spi2, the interfaces should be enabled ++ with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays. ++ ++ The following features of fbtft_device have not been ported over: ++ - parallel bus is not supported ++ - the init property which overrides the controller initialization ++ sequence is not supported as a parameter due to memory limitations in ++ the bootloader responsible for applying the overlay. ++ ++ See https://github.com/notro/fbtft/wiki/FBTFT-RPI-overlays for how to ++ create an overlay. ++ ++Load: dtoverlay=fbtft,= ++Params: ++ spi- Configure device at spi, cs ++ (boolean, required) ++ speed SPI bus speed in Hz (default 32000000) ++ cpha Shifted clock phase (CPHA) mode ++ cpol Inverse clock polarity (CPOL) mode ++ ++ adafruit18 Adafruit 1.8 ++ adafruit22 Adafruit 2.2 (old) ++ adafruit22a Adafruit 2.2 ++ adafruit28 Adafruit 2.8 ++ adafruit13m Adafruit 1.3 OLED ++ admatec_c-berry28 C-Berry28 ++ dogs102 EA DOGS102 ++ er_tftm050_2 ER-TFTM070-2 ++ er_tftm070_5 ER-TFTM070-5 ++ ew24ha0 EW24HA0 ++ ew24ha0_9bit EW24HA0 in 9-bit mode ++ freetronicsoled128 Freetronics OLED128 ++ hy28a HY28A ++ hy28b HY28B ++ itdb28_spi ITDB02-2.8 with SPI interface circuit ++ mi0283qt-2 Watterott MI0283QT-2 ++ mi0283qt-9a Watterott MI0283QT-9A ++ nokia3310 Nokia 3310 ++ nokia3310a Nokia 3310a ++ nokia5110 Nokia 5110 ++ piscreen PiScreen ++ pitft Adafruit PiTFT 2.8 ++ pioled ILSoft OLED ++ rpi-display Watterott rpi-display ++ sainsmart18 Sainsmart 1.8 ++ sainsmart32_spi Sainsmart 3.2 with SPI interfce circuit ++ tinylcd35 TinyLCD 3.5 ++ tm022hdh26 Tianma TM022HDH26 ++ tontec35_9481 Tontect 3.5 with ILI9481 controller ++ tontec35_9486 Tontect 3.5 with ILI9486 controller ++ waveshare32b Waveshare 3.2 ++ waveshare22 Waveshare 2.2 ++ ++ bd663474 BD663474 display controller ++ hx8340bn HX8340BN display controller ++ hx8347d HX8347D display controller ++ hx8353d HX8353D display controller ++ hx8357d HX8357D display controller ++ ili9163 ILI9163 display controller ++ ili9320 ILI9320 display controller ++ ili9325 ILI9325 display controller ++ ili9340 ILI9340 display controller ++ ili9341 ILI9341 display controller ++ ili9481 ILI9481 display controller ++ ili9486 ILI9486 display controller ++ pcd8544 PCD8544 display controller ++ ra8875 RA8875 display controller ++ s6d02a1 S6D02A1 display controller ++ s6d1121 S6D1121 display controller ++ seps525 SEPS525 display controller ++ sh1106 SH1106 display controller ++ ssd1289 SSD1289 display controller ++ ssd1305 SSD1305 display controller ++ ssd1306 SSD1306 display controller ++ ssd1325 SSD1325 display controller ++ ssd1331 SSD1331 display controller ++ ssd1351 SSD1351 display controller ++ st7735r ST7735R display controller ++ st7789v ST7789V display controller ++ tls8204 TLS8204 display controller ++ uc1611 UC1611 display controller ++ uc1701 UC1701 display controller ++ upd161704 UPD161704 display controller ++ ++ width Display width in pixels ++ height Display height in pixels ++ regwidth Display controller register width (default is ++ driver specific) ++ buswidth Display bus interface width (default 8) ++ debug Debug output level {0-7} ++ rotate Display rotation {0, 90, 180, 270} (counter ++ clockwise). Not supported by all drivers. ++ bgr Enable BGR mode (default off). Use if Red and ++ Blue are swapped. Not supported by all drivers. ++ fps Frames per second (default 30). In effect this ++ states how long the driver will wait after video ++ memory has been changed until display update ++ transfer is started. ++ txbuflen Length of the FBTFT transmit buffer ++ (default 4096) ++ startbyte Sets the Start byte used by fb_ili9320, ++ fb_ili9325 and fb_hx8347d. Common value is 0x70. ++ gamma String representation of Gamma Curve(s). Driver ++ specific. Not supported by all drivers. ++ reset_pin GPIO pin for RESET ++ dc_pin GPIO pin for D/C ++ led_pin GPIO pin for LED backlight ++ ++ +Name: fe-pi-audio +Info: Configures the Fe-Pi Audio Sound Card +Load: dtoverlay=fe-pi-audio @@ -10178,6 +11234,11 @@ index 000000000000..5064d8eb2040 + or reboot). This also disables the ability to trigger a boot by driving + GPIO3 low. + ++ The GPIO starts in an inactive state. At poweroff time it is driven ++ active for 100ms, then inactive for 100ms, then active again. It is ++ safe to remove the power at any point after the initial activation of ++ the GPIO. ++ + Users of this overlay are required to provide an external mechanism to + switch off the power supply when signalled - failure to do so results + in a kernel BUG, increased power consumption and undefined behaviour. @@ -10193,6 +11254,8 @@ index 000000000000..5064d8eb2040 + input Set if the gpio pin should be configured as + an input. + export Set to export the configured pin to sysfs ++ active_delay_ms Initial GPIO active period (default 100) ++ inactive_delay_ms Subsequent GPIO inactive period (default 100) + timeout_ms Specify (in ms) how long the kernel waits for + power-down before issuing a WARN (default 3000). + @@ -10725,6 +11788,9 @@ index 000000000000..5064d8eb2040 + + htu21 Select the HTU21 temperature and humidity sensor + ++ int_pin Set the GPIO to use for interrupts (max30102 ++ only) ++ + lm75 Select the Maxim LM75 temperature sensor + Valid addresses 0x48-0x4f, default 0x4f + @@ -10733,6 +11799,9 @@ index 000000000000..5064d8eb2040 + max17040 Select the Maxim Integrated MAX17040 battery + monitor + ++ max30102 Select the Maxim Integrated MAX30102 heart-rate ++ and blood-oxygen sensor ++ + sht3x Select the Sensiron SHT3x temperature and + humidity sensor. Valid addresses 0x44-0x45, + default 0x44 @@ -10859,6 +11928,10 @@ index 000000000000..5064d8eb2040 + 180, default 180) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: imx290 @@ -10879,6 +11952,10 @@ index 000000000000..5064d8eb2040 + 2 = external, default external) + rotation Mounting rotation of the camera sensor (0 or + 180, default 0) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: imx378 @@ -10890,6 +11967,10 @@ index 000000000000..5064d8eb2040 + 180, default 180) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: imx477 @@ -10901,6 +11982,10 @@ index 000000000000..5064d8eb2040 + 180, default 180) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: imx519 @@ -10912,6 +11997,10 @@ index 000000000000..5064d8eb2040 + 180, default 0) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: iqaudio-codec @@ -10975,8 +12064,11 @@ index 000000000000..5064d8eb2040 +Info: Infineon irs1125 TOF camera module. + Uses Unicam 1, which is the standard camera connector on most Pi + variants. -+Load: dtoverlay=irs1125 -+Params: ++Load: dtoverlay=irs1125,= ++Params: media-controller Configure use of Media Controller API for ++ configuring the sensor (default off) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: jedec-spi-nor @@ -11388,6 +12480,10 @@ index 000000000000..5064d8eb2040 + 180, default 0) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: ov7251 @@ -11399,6 +12495,10 @@ index 000000000000..5064d8eb2040 + 180, default 0) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default off) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: ov9281 @@ -11410,6 +12510,10 @@ index 000000000000..5064d8eb2040 + 180, default 0) + orientation Sensor orientation (0 = front, 1 = rear, + 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: papirus @@ -12057,6 +13161,14 @@ index 000000000000..5064d8eb2040 + cs_high This device requires an active-high CS + + ++Name: spi0-0cs ++Info: Don't claim any CS pins for SPI0. Requires a device with its chip ++ select permanently enabled, but frees a GPIO for e.g. a DPI display. ++Load: dtoverlay=spi0-0cs,= ++Params: no_miso Don't claim and use the MISO pin (9), freeing ++ it for other uses. ++ ++ +Name: spi0-1cs +Info: Only use one CS pin for SPI0 +Load: dtoverlay=spi0-1cs,= @@ -12390,6 +13502,10 @@ index 000000000000..5064d8eb2040 + link-frequency Set the link frequency. Only values of 297000000 + (574Mbit/s) and 486000000 (972Mbit/s - default) + are supported by the driver. ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default off) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). + + +Name: tc358743-audio @@ -12554,10 +13670,85 @@ index 000000000000..5064d8eb2040 + + +Name: vc4-kms-dpi-at056tn53v1 -+Info: Enable an Innolux 5.6in VGA TFT connected to DPI interface under KMS. ++Info: This overlay is now deprecated - see vc4-kms-dpi-panel,at056tn53v1 ++Load: ++ ++ ++Name: vc4-kms-dpi-generic ++Info: Enable a generic DPI display under KMS. Default timings are for the ++ Adafruit Kippah with 800x480 panel and RGB666 (GPIOs 0-21) + Requires vc4-kms-v3d to be loaded. -+Load: dtoverlay=vc4-kms-dpi-at056tn53v1 -+Params: ++Load: dtoverlay=vc4-kms-dpi-generic,= ++Params: clock-frequency Display clock frequency (Hz) ++ hactive Horizontal active pixels ++ hfp Horizontal front porch ++ hsync Horizontal sync pulse width ++ hbp Horizontal back porch ++ vactive Vertical active lines ++ vfp Vertical front porch ++ vsync Vertical sync pulse width ++ vbp Vertical back porch ++ hsync-invert Horizontal sync active low ++ vsync-invert Vertical sync active low ++ de-invert Data Enable active low ++ pixclk-invert Negative edge pixel clock ++ width-mm Define the screen width in mm ++ height-mm Define the screen height in mm ++ rgb565 Change to RGB565 output on GPIOs 0-19 ++ rgb666-padhi Change to RGB666 output on GPIOs 0-9, 12-17, and ++ 20-25 ++ rgb888 Change to RGB888 output on GPIOs 0-27 ++ bus-format Override the bus format for a MEDIA_BUS_FMT_* ++ value. NB also overridden by rgbXXX overrides. ++ backlight-gpio Defines a GPIO to be used for backlight control ++ (default of none). ++ backlight-pwm Defines a PWM channel to be used for backlight ++ control (default of none). NB Disables audio ++ headphone output as that also uses PWM. ++ backlight-pwm-chan Choose channel on &pwm node for backlight ++ control. ++ (default 0). ++ backlight-pwm-gpio GPIO pin to be used for the PWM backlight. See ++ pwm-2chan for valid options. ++ (default 18 - note this can only work with ++ rgb666-padhi). ++ backlight-pwm-func Pin function of GPIO used for the PWM ++ backlight. ++ See pwm-2chan for valid options. ++ (default 2). ++ backlight-def-brightness ++ Set the default brightness. Normal range 1-16. ++ (default 16). ++ rotate Display rotation {0,90,180,270} (default 0) ++ ++ ++Name: vc4-kms-dpi-panel ++Info: Enable a preconfigured KMS DPI panel. ++ Requires vc4-kms-v3d to be loaded. ++Load: dtoverlay=vc4-kms-dpi-panel,= ++Params: at056tn53v1 Enable an Innolux 5.6in VGA TFT ++ kippah-7inch Enable an Adafruit Kippah with 7inch panel. ++ mzp280 Enable a Geekworm MZP280 panel. ++ backlight-gpio Defines a GPIO to be used for backlight control ++ (default of none). ++ backlight-pwm Defines a PWM channel to be used for backlight ++ control (default of none). NB Disables audio ++ headphone output as that also uses PWM. ++ backlight-pwm-chan Choose channel on &pwm node for backlight ++ control. ++ (default 0). ++ backlight-pwm-gpio GPIO pin to be used for the PWM backlight. See ++ pwm-2chan for valid options. ++ (default 18 - note this can only work with ++ rgb666-padhi). ++ backlight-pwm-func Pin function of GPIO used for the PWM ++ backlight. ++ See pwm-2chan for valid options. ++ (default 2). ++ backlight-def-brightness ++ Set the default brightness. Normal range 1-16. ++ (default 16). ++ rotate Display rotation {0,90,180,270} (default 0) + + +Name: vc4-kms-dsi-7inch @@ -12595,10 +13786,8 @@ index 000000000000..5064d8eb2040 + + +Name: vc4-kms-kippah-7inch -+Info: Enable the Adafruit DPI Kippah with the 7" Ontat panel attached. -+ Requires vc4-kms-v3d to be loaded. -+Load: dtoverlay=vc4-kms-kippah-7inch -+Params: ++Info: This overlay is now deprecated - see vc4-kms-dpi-panel,kippah-7inch ++Load: + + +Name: vc4-kms-v3d @@ -12617,8 +13806,8 @@ index 000000000000..5064d8eb2040 + cma-default Use upstream's default value + audio Enable or disable audio over HDMI (default "on") + noaudio Disable all HDMI audio (default "off") -+ nocomposite Disable the composite video output (default -+ "off") ++ composite Enable the composite output (default "off") ++ N.B. Disables all other outputs on a Pi 4. + + +Name: vc4-kms-v3d-pi4 @@ -12662,6 +13851,14 @@ index 000000000000..5064d8eb2040 +Params: + + ++Name: vl805 ++Info: Overlay to enable a VIA VL805 USB3 controller on CM4 carriers ++ Will be loaded automatically by up-to-date firmware if "VL805=1" is ++ set in the EEPROM config. ++Load: dtoverlay=vl805 ++Params: ++ ++ +Name: w1-gpio +Info: Configures the w1-gpio Onewire interface module. + Use this overlay if you *don't* need a GPIO to drive an external pullup. @@ -13322,10 +14519,10 @@ index 000000000000..1c5c9b6bb6ff +}; diff --git a/arch/arm/boot/dts/overlays/adv7282m-overlay.dts b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts new file mode 100644 -index 000000000000..5d85dfd0595c +index 000000000000..f7e97c4a13d8 --- /dev/null +++ b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts -@@ -0,0 +1,65 @@ +@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for Analog Devices ADV7282-M video to CSI2 bridge on VC I2C bus +/dts-v1/; @@ -13387,8 +14584,16 @@ index 000000000000..5d85dfd0595c + }; + }; + ++ fragment@4 { ++ target = <&csi1>; ++ __dormant__ { ++ brcm,media-controller; ++ }; ++ }; ++ + __overrides__ { + addr = <&adv728x>,"reg:0"; ++ media-controller = <0>,"=4"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts b/arch/arm/boot/dts/overlays/adv728x-m-overlay.dts @@ -14921,6 +16126,129 @@ index 000000000000..1d87c599f909 + cma-default = <0>,"-0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/cutiepi-panel-overlay.dts b/arch/arm/boot/dts/overlays/cutiepi-panel-overlay.dts +new file mode 100644 +index 000000000000..6f9694e81d6a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/cutiepi-panel-overlay.dts +@@ -0,0 +1,117 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2711"; ++ ++ fragment@0 { ++ target=<&dsi1>; ++ ++ __overlay__ { ++ status = "okay"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port { ++ dsi1_out_port: endpoint { ++ remote-endpoint = <&panel_dsi_in1>; ++ }; ++ }; ++ ++ display1: panel@0 { ++ compatible = "nwe,nwe080"; ++ reg=<0>; ++ backlight = <&rpi_backlight>; ++ reset-gpios = <&gpio 20 0>; ++ port { ++ panel_dsi_in1: endpoint { ++ remote-endpoint = <&dsi1_out_port>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ pwm_pins: pwm_pins { ++ brcm,pins = <12>; ++ brcm,function = <4>; // ALT0 ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&pwm>; ++ frag1: __overlay__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ assigned-clock-rates = <1000000>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "/"; ++ __overlay__ { ++ rpi_backlight: rpi_backlight { ++ compatible = "pwm-backlight"; ++ brightness-levels = <0 6 8 12 16 24 32 40 48 64 96 128 160 192 224 255>; ++ default-brightness-level = <6>; ++ pwms = <&pwm 0 200000>; ++ power-supply = <&vdd_3v3_reg>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c6>; ++ frag0: __overlay__ { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c6_pins>; ++ clock-frequency = <100000>; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&i2c6_pins>; ++ __overlay__ { ++ brcm,pins = <22 23>; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&gpio>; ++ __overlay__ { ++ goodix_pins: goodix_pins { ++ brcm,pins = <21 26>; // interrupt and reset ++ brcm,function = <0 0>; // in ++ brcm,pull = <2 2>; // pull-up ++ }; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&i2c6>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ gt9xx: gt9xx@5d { ++ compatible = "goodix,gt9271"; ++ reg = <0x5D>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&goodix_pins>; ++ interrupt-parent = <&gpio>; ++ interrupts = <21 2>; // high-to-low edge triggered ++ irq-gpios = <&gpio 21 0>; ++ reset-gpios = <&gpio 26 0>; ++ }; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/dht11-overlay.dts b/arch/arm/boot/dts/overlays/dht11-overlay.dts new file mode 100644 index 000000000000..6feeeb402493 @@ -15554,10 +16882,10 @@ index 000000000000..0d83e344ad97 +}; diff --git a/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts new file mode 100644 -index 000000000000..f82b4d0e5047 +index 000000000000..1210e4b8e6dc --- /dev/null +++ b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts -@@ -0,0 +1,10 @@ +@@ -0,0 +1,26 @@ +/* + * Device Tree overlay for EDT 5406 touchscreen controller, as used on the + * Raspberry Pi 7" panel @@ -15568,12 +16896,28 @@ index 000000000000..f82b4d0e5047 +/plugin/; + +#include "edt-ft5406.dtsi" ++ ++/ { ++ fragment@0 { ++ target = <&i2c0if>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2c0mux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/edt-ft5406.dtsi b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi new file mode 100644 -index 000000000000..0473ff17f19f +index 000000000000..2d0ff0e8b24e --- /dev/null +++ b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi -@@ -0,0 +1,55 @@ +@@ -0,0 +1,47 @@ +/* + * Device Tree overlay for an EDT FT5406 touchscreen + * @@ -15603,9 +16947,8 @@ index 000000000000..0473ff17f19f + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; -+ status = "okay"; + ft5406: ts@38 { -+ compatible = "edt,edt-ft5406"; ++ compatible = "edt,edt-ft5506"; + reg = <0x38>; + + touchscreen-size-x = < 800 >; @@ -15614,13 +16957,6 @@ index 000000000000..0473ff17f19f + }; + }; + -+ fragment@13 { -+ target = <&i2c0if>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ + __overrides__ { + sizex = <&ft5406>,"touchscreen-size-x:0"; + sizey = <&ft5406>,"touchscreen-size-y:0"; @@ -15795,6 +17131,623 @@ index 000000000000..6f087fb20661 + swapxy = <&exc3000>,"touchscreen-swapped-x-y?"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/fbtft-overlay.dts b/arch/arm/boot/dts/overlays/fbtft-overlay.dts +new file mode 100644 +index 000000000000..db45f8c53bcc +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/fbtft-overlay.dts +@@ -0,0 +1,611 @@ ++/* ++ * Device Tree overlay for fbtft drivers ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ /* adafruit18 */ ++ fragment@0 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "sitronix,st7735r"; ++ spi-max-frequency = <32000000>; ++ gamma = "02 1c 07 12 37 32 29 2d 29 25 2B 39 00 01 03 10\n03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10"; ++ }; ++ }; ++ ++ /* adafruit22 */ ++ fragment@1 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "himax,hx8340bn"; ++ spi-max-frequency = <32000000>; ++ buswidth = <9>; ++ bgr; ++ }; ++ }; ++ ++ /* adafruit22a */ ++ fragment@2 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9340"; ++ spi-max-frequency = <32000000>; ++ bgr; ++ }; ++ }; ++ ++ /* adafruit28 */ ++ fragment@3 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9341"; ++ spi-max-frequency = <32000000>; ++ bgr; ++ }; ++ }; ++ ++ /* adafruit13m */ ++ fragment@4 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "solomon,ssd1306"; ++ spi-max-frequency = <16000000>; ++ }; ++ }; ++ ++ /* admatec_c-berry28 */ ++ fragment@5 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "sitronix,st7789v"; ++ spi-max-frequency = <48000000>; ++ init = <0x01000011 ++ 0x02000078 ++ 0x0100003A 0x05 ++ 0x010000B2 0x0C 0x0C 0x00 0x33 0x33 ++ 0x010000B7 0x35 ++ 0x010000C2 0x01 0xFF ++ 0x010000C3 0x17 ++ 0x010000C4 0x20 ++ 0x010000BB 0x17 ++ 0x010000C5 0x20 ++ 0x010000D0 0xA4 0xA1 ++ 0x01000029>; ++ gamma = "D0 00 14 15 13 2C 42 43 4E 09 16 14 18 21\nD0 00 14 15 13 0B 43 55 53 0C 17 14 23 20"; ++ }; ++ }; ++ ++ /* dogs102 */ ++ fragment@6 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "UltraChip,uc1701"; ++ spi-max-frequency = <8000000>; ++ bgr; ++ }; ++ }; ++ ++ /* er_tftm050_2 */ ++ fragment@7 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "raio,ra8875"; ++ spi-max-frequency = <5000000>; ++ spi-cpha; ++ spi-cpol; ++ width = <480>; ++ height = <272>; ++ bgr; ++ }; ++ }; ++ ++ /* er_tftm070_5 */ ++ fragment@8 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "raio,ra8875"; ++ spi-max-frequency = <5000000>; ++ spi-cpha; ++ spi-cpol; ++ width = <800>; ++ height = <480>; ++ bgr; ++ }; ++ }; ++ ++ /* ew24ha0 */ ++ fragment@9 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ultrachip,uc1611"; ++ spi-max-frequency = <32000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ /* ew24ha0_9bit */ ++ fragment@10 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ultrachip,uc1611"; ++ spi-max-frequency = <32000000>; ++ spi-cpha; ++ spi-cpol; ++ buswidth = <9>; ++ }; ++ }; ++ ++ /* freetronicsoled128 */ ++ fragment@11 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "solomon,ssd1351"; ++ spi-max-frequency = <20000000>; ++ backlight = <2>; /* FBTFT_ONBOARD_BACKLIGHT */ ++ bgr; ++ }; ++ }; ++ ++ /* hy28a */ ++ fragment@12 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9320"; ++ spi-max-frequency = <32000000>; ++ spi-cpha; ++ spi-cpol; ++ startbyte = <0x70>; ++ bgr; ++ }; ++ }; ++ ++ /* hy28b */ ++ fragment@13 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9325"; ++ spi-max-frequency = <48000000>; ++ spi-cpha; ++ spi-cpol; ++ init = <0x010000e7 0x0010 ++ 0x01000000 0x0001 ++ 0x01000001 0x0100 ++ 0x01000002 0x0700 ++ 0x01000003 0x1030 ++ 0x01000004 0x0000 ++ 0x01000008 0x0207 ++ 0x01000009 0x0000 ++ 0x0100000a 0x0000 ++ 0x0100000c 0x0001 ++ 0x0100000d 0x0000 ++ 0x0100000f 0x0000 ++ 0x01000010 0x0000 ++ 0x01000011 0x0007 ++ 0x01000012 0x0000 ++ 0x01000013 0x0000 ++ 0x02000032 ++ 0x01000010 0x1590 ++ 0x01000011 0x0227 ++ 0x02000032 ++ 0x01000012 0x009c ++ 0x02000032 ++ 0x01000013 0x1900 ++ 0x01000029 0x0023 ++ 0x0100002b 0x000e ++ 0x02000032 ++ 0x01000020 0x0000 ++ 0x01000021 0x0000 ++ 0x02000032 ++ 0x01000050 0x0000 ++ 0x01000051 0x00ef ++ 0x01000052 0x0000 ++ 0x01000053 0x013f ++ 0x01000060 0xa700 ++ 0x01000061 0x0001 ++ 0x0100006a 0x0000 ++ 0x01000080 0x0000 ++ 0x01000081 0x0000 ++ 0x01000082 0x0000 ++ 0x01000083 0x0000 ++ 0x01000084 0x0000 ++ 0x01000085 0x0000 ++ 0x01000090 0x0010 ++ 0x01000092 0x0000 ++ 0x01000093 0x0003 ++ 0x01000095 0x0110 ++ 0x01000097 0x0000 ++ 0x01000098 0x0000 ++ 0x01000007 0x0133 ++ 0x01000020 0x0000 ++ 0x01000021 0x0000 ++ 0x02000064>; ++ startbyte = <0x70>; ++ bgr; ++ fps = <50>; ++ gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; ++ }; ++ }; ++ ++ /* itdb28_spi */ ++ fragment@14 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9325"; ++ spi-max-frequency = <32000000>; ++ bgr; ++ }; ++ }; ++ ++ /* mi0283qt-2 */ ++ fragment@15 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "himax,hx8347d"; ++ spi-max-frequency = <32000000>; ++ startbyte = <0x70>; ++ bgr; ++ }; ++ }; ++ ++ /* mi0283qt-9a */ ++ fragment@16 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9341"; ++ spi-max-frequency = <32000000>; ++ buswidth = <9>; ++ bgr; ++ }; ++ }; ++ ++ /* nokia3310 */ ++ fragment@17 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "philips,pcd8544"; ++ spi-max-frequency = <400000>; ++ }; ++ }; ++ ++ /* nokia3310a */ ++ fragment@18 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "teralane,tls8204"; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ ++ /* nokia5110 */ ++ fragment@19 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9163"; ++ spi-max-frequency = <12000000>; ++ bgr; ++ }; ++ }; ++ ++ /* piscreen */ ++ fragment@20 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9486"; ++ spi-max-frequency = <32000000>; ++ regwidth = <16>; ++ bgr; ++ }; ++ }; ++ ++ /* pitft */ ++ fragment@21 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9340"; ++ spi-max-frequency = <32000000>; ++ init = <0x01000001 ++ 0x02000005 ++ 0x01000028 ++ 0x010000EF 0x03 0x80 0x02 ++ 0x010000CF 0x00 0xC1 0x30 ++ 0x010000ED 0x64 0x03 0x12 0x81 ++ 0x010000E8 0x85 0x00 0x78 ++ 0x010000CB 0x39 0x2C 0x00 0x34 0x02 ++ 0x010000F7 0x20 ++ 0x010000EA 0x00 0x00 ++ 0x010000C0 0x23 ++ 0x010000C1 0x10 ++ 0x010000C5 0x3E 0x28 ++ 0x010000C7 0x86 ++ 0x0100003A 0x55 ++ 0x010000B1 0x00 0x18 ++ 0x010000B6 0x08 0x82 0x27 ++ 0x010000F2 0x00 ++ 0x01000026 0x01 ++ 0x010000E0 0x0F 0x31 0x2B 0x0C 0x0E 0x08 0x4E 0xF1 0x37 0x07 0x10 0x03 0x0E 0x09 0x00 ++ 0x010000E1 0x00 0x0E 0x14 0x03 0x11 0x07 0x31 0xC1 0x48 0x08 0x0F 0x0C 0x31 0x36 0x0F ++ 0x01000011 ++ 0x02000064 ++ 0x01000029 ++ 0x02000014>; ++ bgr; ++ }; ++ }; ++ ++ /* pioled */ ++ fragment@22 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "solomon,ssd1351"; ++ spi-max-frequency = <20000000>; ++ bgr; ++ gamma = "0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4"; ++ }; ++ }; ++ ++ /* rpi-display */ ++ fragment@23 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9341"; ++ spi-max-frequency = <32000000>; ++ bgr; ++ }; ++ }; ++ ++ /* sainsmart18 */ ++ fragment@24 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "sitronix,st7735r"; ++ spi-max-frequency = <32000000>; ++ }; ++ }; ++ ++ /* sainsmart32_spi */ ++ fragment@25 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "solomon,ssd1289"; ++ spi-max-frequency = <16000000>; ++ bgr; ++ }; ++ }; ++ ++ /* tinylcd35 */ ++ fragment@26 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "neosec,tinylcd"; ++ spi-max-frequency = <32000000>; ++ bgr; ++ }; ++ }; ++ ++ /* tm022hdh26 */ ++ fragment@27 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9341"; ++ spi-max-frequency = <32000000>; ++ bgr; ++ }; ++ }; ++ ++ /* tontec35_9481 - boards before 02 July 2014 */ ++ fragment@28 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9481"; ++ spi-max-frequency = <128000000>; ++ spi-cpha; ++ spi-cpol; ++ bgr; ++ }; ++ }; ++ ++ /* tontec35_9486 - boards after 02 July 2014 */ ++ fragment@29 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9486"; ++ spi-max-frequency = <128000000>; ++ spi-cpha; ++ spi-cpol; ++ bgr; ++ }; ++ }; ++ ++ /* waveshare32b */ ++ fragment@30 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "ilitek,ili9340"; ++ spi-max-frequency = <48000000>; ++ init = <0x010000CB 0x39 0x2C 0x00 0x34 0x02 ++ 0x010000CF 0x00 0xC1 0x30 ++ 0x010000E8 0x85 0x00 0x78 ++ 0x010000EA 0x00 0x00 ++ 0x010000ED 0x64 0x03 0x12 0x81 ++ 0x010000F7 0x20 ++ 0x010000C0 0x23 ++ 0x010000C1 0x10 ++ 0x010000C5 0x3E 0x28 ++ 0x010000C7 0x86 ++ 0x01000036 0x28 ++ 0x0100003A 0x55 ++ 0x010000B1 0x00 0x18 ++ 0x010000B6 0x08 0x82 0x27 ++ 0x010000F2 0x00 ++ 0x01000026 0x01 ++ 0x010000E0 0x0F 0x31 0x2B 0x0C 0x0E 0x08 0x4E 0xF1 0x37 0x07 0x10 0x03 0x0E 0x09 0x00 ++ 0x010000E1 0x00 0x0E 0x14 0x03 0x11 0x07 0x31 0xC1 0x48 0x08 0x0F 0x0C 0x31 0x36 0x0F ++ 0x01000011 ++ 0x02000078 ++ 0x01000029 ++ 0x0100002C>; ++ bgr; ++ }; ++ }; ++ ++ /* waveshare22 */ ++ fragment@31 { ++ target = <&display>; ++ __dormant__ { ++ compatible = "hitachi,bd663474"; ++ spi-max-frequency = <32000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spidev_fragment: fragment@100 { ++ target-path = "spi0/spidev@0"; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ display_fragment: fragment@101 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ display: display@0{ ++ reg = <0>; ++ spi-max-frequency = <32000000>; ++ fps = <30>; ++ buswidth = <8>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ spi0-0 = <&display_fragment>, "target:0=",<&spi0>, ++ <&spidev_fragment>, "target-path=spi0/spidev@0", ++ <&display>, "reg:0=0"; ++ spi0-1 = <&display_fragment>, "target:0=",<&spi0>, ++ <&spidev_fragment>, "target-path=spi0/spidev@1", ++ <&display>, "reg:0=1"; ++ spi1-0 = <&display_fragment>, "target:0=",<&spi1>, ++ <&spidev_fragment>, "target-path=spi1/spidev@0", ++ <&display>, "reg:0=0"; ++ spi1-1 = <&display_fragment>, "target:0=",<&spi1>, ++ <&spidev_fragment>, "target-path=spi1/spidev@1", ++ <&display>, "reg:0=1"; ++ spi1-2 = <&display_fragment>, "target:0=",<&spi1>, ++ <&spidev_fragment>, "target-path=spi1/spidev@2", ++ <&display>, "reg:0=2"; ++ spi2-0 = <&display_fragment>, "target:0=",<&spi2>, ++ <&spidev_fragment>, "target-path=spi2/spidev@0", ++ <&display>, "reg:0=0"; ++ spi2-1 = <&display_fragment>, "target:0=",<&spi2>, ++ <&spidev_fragment>, "target-path=spi2/spidev@1", ++ <&display>, "reg:0=1"; ++ spi2-2 = <&display_fragment>, "target:0=",<&spi2>, ++ <&spidev_fragment>, "target-path=spi2/spidev@2", ++ <&display>, "reg:0=2"; ++ ++ speed = <&display>, "spi-max-frequency:0"; ++ cpha = <&display>, "spi-cpha?"; ++ cpol = <&display>, "spi-cpol?"; ++ ++ /* Displays */ ++ adafruit18 = <0>, "+0"; ++ adafruit22 = <0>, "+1"; ++ adafruit22a = <0>, "+2"; ++ adafruit28 = <0>, "+3"; ++ adafruit13m = <0>, "+4"; ++ admatec_c-berry28 = <0>, "+5"; ++ dogs102 = <0>, "+6"; ++ er_tftm050_2 = <0>, "+7"; ++ er_tftm070_5 = <0>, "+8"; ++ ew24ha0 = <0>, "+9"; ++ ew24ha0_9bit = <0>, "+10"; ++ freetronicsoled128 = <0>, "+11"; ++ hy28a = <0>, "+12"; ++ hy28b = <0>, "+13"; ++ itdb28_spi = <0>, "+14"; ++ mi0283qt-2 = <0>, "+15"; ++ mi0283qt-9a = <0>, "+16"; ++ nokia3310 = <0>, "+17"; ++ nokia3310a = <0>, "+18"; ++ nokia5110 = <0>, "+19"; ++ piscreen = <0>, "+20"; ++ pitft = <0>, "+21"; ++ pioled = <0>, "+22"; ++ rpi-display = <0>, "+23"; ++ sainsmart18 = <0>, "+24"; ++ sainsmart32_spi = <0>, "+25"; ++ tinylcd35 = <0>, "+26"; ++ tm022hdh26 = <0>, "+27"; ++ tontec35_9481 = <0>, "+28"; ++ tontec35_9486 = <0>, "+29"; ++ waveshare32b = <0>, "+30"; ++ waveshare22 = <0>, "+31"; ++ ++ /* Controllers */ ++ bd663474 = <&display>, "compatible=hitachi,bd663474"; ++ hx8340bn = <&display>, "compatible=himax,hx8340bn"; ++ hx8347d = <&display>, "compatible=himax,hx8347d"; ++ hx8353d = <&display>, "compatible=himax,hx8353d"; ++ hx8357d = <&display>, "compatible=himax,hx8357d"; ++ ili9163 = <&display>, "compatible=ilitek,ili9163"; ++ ili9320 = <&display>, "compatible=ilitek,ili9320"; ++ ili9325 = <&display>, "compatible=ilitek,ili9325"; ++ ili9340 = <&display>, "compatible=ilitek,ili9340"; ++ ili9341 = <&display>, "compatible=ilitek,ili9341"; ++ ili9481 = <&display>, "compatible=ilitek,ili9481"; ++ ili9486 = <&display>, "compatible=ilitek,ili9486"; ++ pcd8544 = <&display>, "compatible=philips,pcd8544"; ++ ra8875 = <&display>, "compatible=raio,ra8875"; ++ s6d02a1 = <&display>, "compatible=samsung,s6d02a1"; ++ s6d1121 = <&display>, "compatible=samsung,s6d1121"; ++ seps525 = <&display>, "compatible=syncoam,seps525"; ++ sh1106 = <&display>, "compatible=sinowealth,sh1106"; ++ ssd1289 = <&display>, "compatible=solomon,ssd1289"; ++ ssd1305 = <&display>, "compatible=solomon,ssd1305"; ++ ssd1306 = <&display>, "compatible=solomon,ssd1306"; ++ ssd1325 = <&display>, "compatible=solomon,ssd1325"; ++ ssd1331 = <&display>, "compatible=solomon,ssd1331"; ++ ssd1351 = <&display>, "compatible=solomon,ssd1351"; ++ st7735r = <&display>, "compatible=sitronix,st7735r"; ++ st7789v = <&display>, "compatible=sitronix,st7789v"; ++ tls8204 = <&display>, "compatible=teralane,tls8204"; ++ uc1611 = <&display>, "compatible=ultrachip,uc1611"; ++ uc1701 = <&display>, "compatible=UltraChip,uc1701"; ++ upd161704 = <&display>, "compatible=nec,upd161704"; ++ ++ width = <&display>, "width:0"; ++ height = <&display>, "height:0"; ++ regwidth = <&display>, "regwidth:0"; ++ buswidth = <&display>, "buswidth:0"; ++ debug = <&display>, "debug:0"; ++ rotate = <&display>, "rotate:0"; ++ bgr = <&display>, "bgr?"; ++ fps = <&display>, "fps:0"; ++ txbuflen = <&display>, "txbuflen:0"; ++ startbyte = <&display>, "startbyte:0"; ++ gamma = <&display>, "gamma"; ++ ++ reset_pin = <&display>, "reset-gpios:0=", <&gpio>, ++ <&display>, "reset-gpios:4", ++ <&display>, "reset-gpios:8=1"; /* GPIO_ACTIVE_LOW */ ++ dc_pin = <&display>, "dc-gpios:0=", <&gpio>, ++ <&display>, "dc-gpios:4", ++ <&display>, "dc-gpios:8=0"; /* GPIO_ACTIVE_HIGH */ ++ led_pin = <&display>, "led-gpios:0=", <&gpio>, ++ <&display>, "led-gpios:4", ++ <&display>, "led-gpios:8=0"; /* GPIO_ACTIVE_HIGH */ ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts new file mode 100644 index 000000000000..743f14ae5768 @@ -16620,10 +18573,10 @@ index 000000000000..55f9bff3a8f6 +}; diff --git a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts new file mode 100644 -index 000000000000..416aa2bc797a +index 000000000000..8153f83f0427 --- /dev/null +++ b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts -@@ -0,0 +1,37 @@ +@@ -0,0 +1,39 @@ +// Definitions for gpio-poweroff module +/dts-v1/; +/plugin/; @@ -16659,6 +18612,8 @@ index 000000000000..416aa2bc797a + input = <&power_ctrl>,"input?"; + export = <&power_ctrl>,"export?"; + timeout_ms = <&power_ctrl>,"timeout-ms:0"; ++ active_delay_ms = <&power_ctrl>,"active-delay-ms:0"; ++ inactive_delay_ms = <&power_ctrl>,"inactive-delay-ms:0"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts @@ -18668,10 +20623,10 @@ index 000000000000..1eae9e1a5c96 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts new file mode 100755 -index 000000000000..b05b0fa91942 +index 000000000000..33965be4b1e8 --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -0,0 +1,320 @@ +@@ -0,0 +1,340 @@ +// Definitions for I2C based sensors using the Industrial IO or HWMON interface. +/dts-v1/; +/plugin/; @@ -18965,11 +20920,30 @@ index 000000000000..b05b0fa91942 + }; + }; + ++ fragment@19 { ++ target = <&i2c_arm>; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ max30102: max30102@57 { ++ compatible = "maxim,max30102"; ++ reg = <0x57>; ++ maxim,red-led-current-microamp = <7000>; ++ maxim,ir-led-current-microamp = <7000>; ++ interrupt-parent = <&gpio>; ++ interrupts = <4 2>; ++ }; ++ }; ++ }; ++ + __overrides__ { + addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0", + <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0", + <&ds1621>,"reg:0", <&bme680>,"reg:0", <&ccs811>,"reg:0", + <&bh1750>,"reg:0"; ++ int_pin = <&max30102>, "interrupts:0"; + bme280 = <0>,"+0"; + bmp085 = <0>,"+1"; + bmp180 = <0>,"+2"; @@ -18990,6 +20964,7 @@ index 000000000000..b05b0fa91942 + sgp30 = <0>,"+16"; + ccs811 = <0>, "+17"; + bh1750 = <0>, "+18"; ++ max30102 = <0>,"+19"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/i2c0-overlay.dts b/arch/arm/boot/dts/overlays/i2c0-overlay.dts @@ -19376,10 +21351,10 @@ index 000000000000..551aba591d26 +}; diff --git a/arch/arm/boot/dts/overlays/imx219-overlay.dts b/arch/arm/boot/dts/overlays/imx219-overlay.dts new file mode 100644 -index 000000000000..0c065bf09f54 +index 000000000000..bc1217397dd5 --- /dev/null +++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts -@@ -0,0 +1,115 @@ +@@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for IMX219 camera module on VC I2C bus +/dts-v1/; @@ -19391,6 +21366,28 @@ index 000000000000..0c065bf09f54 + compatible = "brcm,bcm2835"; + + fragment@0 { ++ target = <&i2c0if>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ clk_frag: fragment@1 { ++ target = <&cam1_clk>; ++ __overlay__ { ++ status = "okay"; ++ clock-frequency = <24000000>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c0mux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ i2c_frag: fragment@100 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -19402,19 +21399,19 @@ index 000000000000..0c065bf09f54 + reg = <0x10>; + status = "okay"; + -+ clocks = <&imx219_clk>; ++ clocks = <&cam1_clk>; + clock-names = "xclk"; + + VANA-supply = <&cam1_reg>; /* 2.8v */ -+ VDIG-supply = <&imx219_vdig>; /* 1.8v */ -+ VDDL-supply = <&imx219_vddl>; /* 1.2v */ ++ VDIG-supply = <&cam_dummy_reg>; /* 1.8v */ ++ VDDL-supply = <&cam_dummy_reg>; /* 1.2v */ + + rotation = <180>; + orientation = <2>; + + port { + imx219_0: endpoint { -+ remote-endpoint = <&csi1_ep>; ++ remote-endpoint = <&csi_ep>; + clock-lanes = <0>; + data-lanes = <1 2>; + clock-noncontinuous; @@ -19426,13 +21423,14 @@ index 000000000000..0c065bf09f54 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@101 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; ++ brcm,media-controller; + + port { -+ csi1_ep: endpoint { ++ csi_ep: endpoint { + remote-endpoint = <&imx219_0>; + clock-lanes = <0>; + data-lanes = <1 2>; @@ -19442,57 +21440,15 @@ index 000000000000..0c065bf09f54 + }; + }; + -+ fragment@2 { -+ target = <&i2c0if>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path="/"; -+ __overlay__ { -+ imx219_vdig: fixedregulator@1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx219_vdig"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ imx219_vddl: fixedregulator@2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx219_vddl"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ }; -+ -+ imx219_clk: camera-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c0mux>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&cam1_reg>; -+ __overlay__ { -+ status = "okay"; -+ regulator-name = "imx219_vana"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; -+ }; -+ }; -+ + __overrides__ { + rotation = <&imx219>,"rotation:0"; + orientation = <&imx219>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&imx219>, "clocks:0=",<&cam0_clk>, ++ <&imx219>, "VANA-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/imx290-overlay.dts b/arch/arm/boot/dts/overlays/imx290-overlay.dts @@ -19535,10 +21491,10 @@ index 000000000000..e536aa7f9e33 +}; diff --git a/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi b/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi new file mode 100644 -index 000000000000..d4a5ed6dbbcf +index 000000000000..111d69597554 --- /dev/null +++ b/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi -@@ -0,0 +1,144 @@ +@@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Partial definitions for IMX290 or IMX327 camera module on VC I2C bus +// The compatible string should be set in an overlay that then includes this one @@ -19550,7 +21506,7 @@ index 000000000000..d4a5ed6dbbcf +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -19561,7 +21517,7 @@ index 000000000000..d4a5ed6dbbcf + reg = <0x1a>; + status = "okay"; + -+ clocks = <&imx290_clk>; ++ clocks = <&cam1_clk>; + clock-names = "xclk"; + clock-frequency = <37125000>; + @@ -19569,8 +21525,8 @@ index 000000000000..d4a5ed6dbbcf + orientation = <2>; + + vdda-supply = <&cam1_reg>; /* 2.8v */ -+ vdddo-supply = <&imx290_vdddo>; /* 1.8v */ -+ vddd-supply = <&imx290_vddd>; /* 1.5v */ ++ vdddo-supply = <&cam_dummy_reg>; /* 1.8v */ ++ vddd-supply = <&cam_dummy_reg>; /* 1.5v */ + + port { + imx290_0: endpoint { @@ -19582,10 +21538,11 @@ index 000000000000..d4a5ed6dbbcf + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; ++ brcm,media-controller; + + port { + csi1_ep: endpoint { @@ -19602,27 +21559,11 @@ index 000000000000..d4a5ed6dbbcf + }; + }; + -+ fragment@3 { -+ target-path="/"; -+ __overlay__ { -+ imx290_vdddo: fixedregulator@1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx290_vdddo"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ imx290_vddd: fixedregulator@2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx290_vddd"; -+ regulator-min-microvolt = <1500000>; -+ regulator-max-microvolt = <1500000>; -+ }; -+ -+ imx290_clk: camera-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <37125000>; -+ }; ++ clk_frag: fragment@3 { ++ target = <&cam1_clk>; ++ cam_clk: __overlay__ { ++ status = "okay"; ++ clock-frequency = <37125000>; + }; + }; + @@ -19633,16 +21574,6 @@ index 000000000000..d4a5ed6dbbcf + }; + }; + -+ fragment@5 { -+ target = <&cam1_reg>; -+ __overlay__ { -+ status = "okay"; -+ regulator-name = "imx290_vdda"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; -+ }; -+ }; -+ + fragment@6 { + target = <&imx290_0>; + __overlay__ { @@ -19677,10 +21608,16 @@ index 000000000000..d4a5ed6dbbcf + + __overrides__ { + 4lane = <0>, "-6+7-8+9"; -+ clock-frequency = <&imx290_clk>,"clock-frequency:0", ++ clock-frequency = <&cam_clk>,"clock-frequency:0", + <&imx290>,"clock-frequency:0"; + rotation = <&imx290>,"rotation:0"; + orientation = <&imx290>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&imx290>, "clocks:0=",<&cam0_clk>, ++ <&imx290>, "vdda-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/imx378-overlay.dts b/arch/arm/boot/dts/overlays/imx378-overlay.dts @@ -19717,17 +21654,46 @@ index 000000000000..ca315d120e6b +}; diff --git a/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi new file mode 100644 -index 000000000000..bb9a9acdbbd7 +index 000000000000..bfea40ce98d6 --- /dev/null +++ b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi -@@ -0,0 +1,110 @@ +@@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for IMX477 camera module on VC I2C bus + +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ fragment@2 { ++ target = <&i2c0if>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ clk_frag: fragment@3 { ++ target = <&cam1_clk>; ++ cam_clk: __overlay__ { ++ clock-frequency = <24000000>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c0mux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ reg_frag: fragment@5 { ++ target = <&cam1_reg>; ++ cam_reg: __overlay__ { ++ startup-delay-us = <300000>; ++ }; ++ }; ++ ++ i2c_frag: fragment@100 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -19738,19 +21704,19 @@ index 000000000000..bb9a9acdbbd7 + reg = <0x1a>; + status = "okay"; + -+ clocks = <&imx477_clk>; ++ clocks = <&cam1_clk>; + clock-names = "xclk"; + + VANA-supply = <&cam1_reg>; /* 2.8v */ -+ VDIG-supply = <&imx477_vdig>; /* 1.05v */ -+ VDDL-supply = <&imx477_vddl>; /* 1.8v */ ++ VDIG-supply = <&cam_dummy_reg>; /* 1.05v */ ++ VDDL-supply = <&cam_dummy_reg>; /* 1.8v */ + + rotation = <180>; + orientation = <2>; + + port { + imx477_0: endpoint { -+ remote-endpoint = <&csi1_ep>; ++ remote-endpoint = <&csi_ep>; + clock-lanes = <0>; + data-lanes = <1 2>; + clock-noncontinuous; @@ -19762,13 +21728,14 @@ index 000000000000..bb9a9acdbbd7 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@101 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; ++ brcm,media-controller; + + port { -+ csi1_ep: endpoint { ++ csi_ep: endpoint { + remote-endpoint = <&imx477_0>; + clock-lanes = <0>; + data-lanes = <1 2>; @@ -19778,65 +21745,24 @@ index 000000000000..bb9a9acdbbd7 + }; + }; + -+ fragment@2 { -+ target = <&i2c0if>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path="/"; -+ __overlay__ { -+ imx477_vdig: fixedregulator@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx477_vdig"; -+ regulator-min-microvolt = <1050000>; -+ regulator-max-microvolt = <1050000>; -+ }; -+ imx477_vddl: fixedregulator@1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx477_vddl"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ imx477_clk: camera-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c0mux>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&cam1_reg>; -+ __overlay__ { -+ status = "okay"; -+ regulator-name = "imx477_vana"; -+ startup-delay-us = <300000>; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; -+ }; -+ }; -+ + __overrides__ { + rotation = <&imx477>,"rotation:0"; + orientation = <&imx477>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <®_frag>, "target:0=",<&cam0_reg>, ++ <&imx477>, "clocks:0=",<&cam0_clk>, ++ <&imx477>, "vdda-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/imx519-overlay.dts b/arch/arm/boot/dts/overlays/imx519-overlay.dts new file mode 100644 -index 000000000000..693c267af1f0 +index 000000000000..ada1224dd19b --- /dev/null +++ b/arch/arm/boot/dts/overlays/imx519-overlay.dts -@@ -0,0 +1,115 @@ +@@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for imx519 camera module on VC I2C bus +/dts-v1/; @@ -19847,7 +21773,7 @@ index 000000000000..693c267af1f0 +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -19859,12 +21785,12 @@ index 000000000000..693c267af1f0 + reg = <0x1a>; + status = "okay"; + -+ clocks = <&imx519_clk>; ++ clocks = <&cam1_clk>; + clock-names = "xclk"; + + VANA-supply = <&cam1_reg>; /* 2.8v */ -+ VDIG-supply = <&imx519_vdig>; /* 1.8v */ -+ VDDL-supply = <&imx519_vddl>; /* 1.2v */ ++ VDIG-supply = <&cam_dummy_reg>; /* 1.8v */ ++ VDDL-supply = <&cam_dummy_reg>; /* 1.2v */ + + rotation = <0>; + orientation = <2>; @@ -19883,10 +21809,11 @@ index 000000000000..693c267af1f0 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; ++ brcm,media-controller; + + port{ + csi1_ep: endpoint{ @@ -19906,27 +21833,11 @@ index 000000000000..693c267af1f0 + }; + }; + -+ fragment@3 { -+ target-path="/"; ++ clk_frag: fragment@3 { ++ target = <&cam1_clk>; + __overlay__ { -+ imx519_vdig: fixedregulator@1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx519_vdig"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ imx519_vddl: fixedregulator@2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "imx519_vddl"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ }; -+ -+ imx519_clk: camera-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ }; ++ clock-frequency = <24000000>; ++ status = "okay"; + }; + }; + @@ -19937,19 +21848,15 @@ index 000000000000..693c267af1f0 + }; + }; + -+ fragment@5 { -+ target = <&cam1_reg>; -+ __overlay__ { -+ status = "okay"; -+ regulator-name = "imx519_vana"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; -+ }; -+ }; -+ + __overrides__ { + rotation = <&imx519>,"rotation:0"; + orientation = <&imx519>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&imx519>, "clocks:0=",<&cam0_clk>, ++ <&imx519>, "VANA-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts @@ -20162,10 +22069,10 @@ index 000000000000..ee54095c869b +}; diff --git a/arch/arm/boot/dts/overlays/irs1125-overlay.dts b/arch/arm/boot/dts/overlays/irs1125-overlay.dts new file mode 100644 -index 000000000000..e926e18e71fc +index 000000000000..8f8432c07a89 --- /dev/null +++ b/arch/arm/boot/dts/overlays/irs1125-overlay.dts -@@ -0,0 +1,85 @@ +@@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for IRS1125 camera module on VC I2C bus +/dts-v1/; @@ -20174,20 +22081,20 @@ index 000000000000..e926e18e71fc +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + -+ irs1125: irs1125@3D { ++ irs1125: irs1125@3d { + compatible = "infineon,irs1125"; -+ reg = <0x3D>; ++ reg = <0x3d>; + status = "okay"; + + pwdn-gpios = <&gpio 5 0>; -+ clocks = <&irs1125_clk>; ++ clocks = <&cam1_clk>; + + port { + irs1125_0: endpoint { @@ -20203,9 +22110,9 @@ index 000000000000..e926e18e71fc + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; + + port { @@ -20240,16 +22147,21 @@ index 000000000000..e926e18e71fc + }; + }; + -+ fragment@5 { -+ target-path = "/"; ++ clk_frag: fragment@5 { ++ target = <&cam1_clk>; + __overlay__ { -+ irs1125_clk: camera-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <26000000>; -+ }; ++ status = "okay"; ++ clock-frequency = <26000000>; + }; + }; ++ ++ __overrides__ { ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&irs1125>, "clocks:0=",<&cam0_clk>; ++ }; +}; diff --git a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts new file mode 100644 @@ -24024,10 +25936,10 @@ index 000000000000..6e00e8b2ddf2 +}; diff --git a/arch/arm/boot/dts/overlays/ov5647-overlay.dts b/arch/arm/boot/dts/overlays/ov5647-overlay.dts new file mode 100644 -index 000000000000..d7ed4703c9b0 +index 000000000000..a1221024d334 --- /dev/null +++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts -@@ -0,0 +1,94 @@ +@@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for OV5647 camera module on VC I2C bus +/dts-v1/; @@ -24036,7 +25948,7 @@ index 000000000000..d7ed4703c9b0 +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -24048,8 +25960,11 @@ index 000000000000..d7ed4703c9b0 + reg = <0x36>; + status = "okay"; + -+ pwdn-gpios = <&gpio 41 1>, <&gpio 32 1>; -+ clocks = <&ov5647_clk>; ++ clocks = <&cam1_clk>; ++ ++ avdd-supply = <&cam1_reg>; ++ dovdd-supply = <&cam_dummy_reg>; ++ dvdd-supply = <&cam_dummy_reg>; + + rotation = <0>; + orientation = <2>; @@ -24068,10 +25983,11 @@ index 000000000000..d7ed4703c9b0 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; ++ brcm,media-controller; + + port { + csi1_ep: endpoint { @@ -24096,38 +26012,39 @@ index 000000000000..d7ed4703c9b0 + }; + }; + -+ fragment@4 { -+ target-path="/__overrides__"; ++ reg_frag: fragment@4 { ++ target = <&cam1_reg>; + __overlay__ { -+ cam0-pwdn-ctrl = <&ov5647>,"pwdn-gpios:0"; -+ cam0-pwdn = <&ov5647>,"pwdn-gpios:4"; -+ cam0-led-ctrl = <&ov5647>,"pwdn-gpios:12"; -+ cam0-led = <&ov5647>,"pwdn-gpios:16"; ++ startup-delay-us = <20000>; + }; + }; + -+ fragment@5 { -+ target-path = "/"; ++ clk_frag: fragment@5 { ++ target = <&cam1_clk>; + __overlay__ { -+ ov5647_clk: camera-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <25000000>; -+ }; ++ status = "okay"; ++ clock-frequency = <25000000>; + }; + }; + + __overrides__ { + rotation = <&ov5647>,"rotation:0"; + orientation = <&ov5647>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <®_frag>, "target:0=",<&cam0_reg>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&ov5647>, "clocks:0=",<&cam0_clk>, ++ <&ov5647>, "avdd-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/ov7251-overlay.dts b/arch/arm/boot/dts/overlays/ov7251-overlay.dts new file mode 100644 -index 000000000000..09dbeda39d06 +index 000000000000..0e44be8a4468 --- /dev/null +++ b/arch/arm/boot/dts/overlays/ov7251-overlay.dts -@@ -0,0 +1,113 @@ +@@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for OV7251 camera module on VC I2C bus +/dts-v1/; @@ -24138,7 +26055,7 @@ index 000000000000..09dbeda39d06 +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -24150,13 +26067,13 @@ index 000000000000..09dbeda39d06 + reg = <0x60>; + status = "okay"; + -+ clocks = <&ov7251_clk>; ++ clocks = <&cam1_clk>; + clock-names = "xclk"; + clock-frequency = <24000000>; + -+ vdddo-supply = <&ov7251_dovdd>; ++ vdddo-supply = <&cam_dummy_reg>; + vdda-supply = <&cam1_reg>; -+ vddd-supply = <&ov7251_dvdd>; ++ vddd-supply = <&cam_dummy_reg>; + + rotation = <0>; + orientation = <2>; @@ -24175,9 +26092,9 @@ index 000000000000..09dbeda39d06 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; + + port { @@ -24197,56 +26114,37 @@ index 000000000000..09dbeda39d06 + }; + + fragment@3 { -+ target-path="/"; -+ __overlay__ { -+ ov7251_dovdd: fixedregulator@1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "ov7251_dovdd"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ ov7251_dvdd: fixedregulator@2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "ov7251_dvdd"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ }; -+ ov7251_clk: ov7251-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { + target = <&i2c0mux>; + __overlay__ { + status = "okay"; + }; + }; + -+ fragment@5 { -+ target = <&cam1_reg>; ++ clk_frag: fragment@4 { ++ target = <&cam1_clk>; + __overlay__ { + status = "okay"; -+ regulator-name = "ov7251_avdd"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; ++ clock-frequency = <24000000>; + }; + }; + + __overrides__ { + rotation = <&ov7251>,"rotation:0"; + orientation = <&ov7251>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&ov7251>, "clocks:0=",<&cam0_clk>, ++ <&ov7251>, "vdda-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/ov9281-overlay.dts b/arch/arm/boot/dts/overlays/ov9281-overlay.dts new file mode 100644 -index 000000000000..277236c03358 +index 000000000000..8c08a3a1077c --- /dev/null +++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts -@@ -0,0 +1,113 @@ +@@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for OV9281 camera module on VC I2C bus +/dts-v1/; @@ -24257,7 +26155,7 @@ index 000000000000..277236c03358 +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; @@ -24269,12 +26167,12 @@ index 000000000000..277236c03358 + reg = <0x60>; + status = "okay"; + -+ clocks = <&ov9281_clk>; ++ clocks = <&cam1_clk>; + clock-names = "xvclk"; + + avdd-supply = <&cam1_reg>; -+ dovdd-supply = <&ov9281_dovdd>; -+ dvdd-supply = <&ov9281_dvdd>; ++ dovdd-supply = <&cam_dummy_reg>; ++ dvdd-supply = <&cam_dummy_reg>; + + rotation = <0>; + orientation = <2>; @@ -24293,10 +26191,11 @@ index 000000000000..277236c03358 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; ++ brcm,media-controller; + + port { + csi1_ep: endpoint { @@ -24316,56 +26215,37 @@ index 000000000000..277236c03358 + }; + + fragment@3 { -+ target-path="/"; -+ __overlay__ { -+ ov9281_dovdd: fixedregulator@1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "ov9281_dovdd"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ ov9281_dvdd: fixedregulator@2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "ov9281_dvdd"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ }; -+ ov9281_clk: ov9281-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { + target = <&i2c0mux>; + __overlay__ { + status = "okay"; + }; + }; + -+ fragment@5 { -+ target = <&cam1_reg>; ++ clk_frag: fragment@4 { ++ target = <&cam1_clk>; + __overlay__ { + status = "okay"; -+ regulator-name = "ov9281_avdd"; -+ regulator-min-microvolt = <2800000>; -+ regulator-max-microvolt = <2800000>; ++ clock-frequency = <24000000>; + }; + }; + + __overrides__ { + rotation = <&ov9281>,"rotation:0"; + orientation = <&ov9281>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&ov9281>, "clocks:0=",<&cam0_clk>, ++ <&ov9281>, "avdd-supply:0=",<&cam0_reg>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/overlay_map.dts b/arch/arm/boot/dts/overlays/overlay_map.dts new file mode 100644 -index 000000000000..bc6e3bce22c7 +index 000000000000..0e01f46d8db0 --- /dev/null +++ b/arch/arm/boot/dts/overlays/overlay_map.dts -@@ -0,0 +1,158 @@ +@@ -0,0 +1,166 @@ +/dts-v1/; + +/ { @@ -24373,6 +26253,10 @@ index 000000000000..bc6e3bce22c7 + deprecated = "use i2c-sensor,bmp085"; + }; + ++ cutiepi-panel { ++ bcm2711; ++ }; ++ + highperi { + bcm2711; + }; @@ -24515,6 +26399,10 @@ index 000000000000..bc6e3bce22c7 + bcm2711; + }; + ++ vc4-kms-dpi-at056tn53v1 { ++ deprecated = "use vc4-kms-dpi-panel,at056tn53v1"; ++ }; ++ + vc4-kms-v3d { + bcm2835; + bcm2711 = "vc4-kms-v3d-pi4"; @@ -24867,10 +26755,10 @@ index 000000000000..8b6ee44665ce +}; diff --git a/arch/arm/boot/dts/overlays/pcie-32bit-dma-overlay.dts b/arch/arm/boot/dts/overlays/pcie-32bit-dma-overlay.dts new file mode 100644 -index 000000000000..cca3e83721b7 +index 000000000000..955703563df7 --- /dev/null +++ b/arch/arm/boot/dts/overlays/pcie-32bit-dma-overlay.dts -@@ -0,0 +1,18 @@ +@@ -0,0 +1,38 @@ +/* + * pcie-32bit-dma-overlay.dts + */ @@ -24884,10 +26772,30 @@ index 000000000000..cca3e83721b7 + fragment@0 { + target-path = "/aliases"; + __overlay__ { ++ /* ++ * Removing this alias stops the firmware patching the ++ * PCIE DT dma-ranges based on the detected chip ++ * revision. ++ */ + pcie0 = ""; + }; + }; + ++ fragment@1 { ++ target = <&pcie0>; ++ __overlay__ { ++ /* ++ * The size of the range is rounded up to a power of 2, ++ * so the range ends up being 0-4GB, and the MSI vector ++ * gets pushed beyond 4GB. ++ */ ++ #address-cells = <3>; ++ #size-cells = <2>; ++ dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000 ++ 0x0 0x80000000>; ++ }; ++ }; ++ +}; diff --git a/arch/arm/boot/dts/overlays/pibell-overlay.dts b/arch/arm/boot/dts/overlays/pibell-overlay.dts new file mode 100644 @@ -26832,7 +28740,7 @@ index 000000000000..07a915342702 +}; diff --git a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts new file mode 100644 -index 000000000000..de87432ff2be +index 000000000000..2cf937b56456 --- /dev/null +++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts @@ -0,0 +1,91 @@ @@ -26899,7 +28807,7 @@ index 000000000000..de87432ff2be + buswidth = <8>; + reset-gpios = <&gpio 23 1>; + dc-gpios = <&gpio 24 0>; -+ led-gpios = <&gpio 18 0>; ++ led-gpios = <&gpio 18 1>; + debug = <0>; + }; + @@ -28465,6 +30373,51 @@ index 000000000000..51b7fec281c0 + pcf2123 = <0>,"+2"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/spi0-0cs-overlay.dts b/arch/arm/boot/dts/overlays/spi0-0cs-overlay.dts +new file mode 100644 +index 000000000000..0d2acabf56a4 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi0-0cs-overlay.dts +@@ -0,0 +1,39 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&spi0_cs_pins>; ++ frag0: __overlay__ { ++ brcm,pins; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0>; ++ __overlay__ { ++ cs-gpios; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spidev1>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&spi0_pins>; ++ __dormant__ { ++ brcm,pins = <10 11>; ++ }; ++ }; ++ ++ __overrides__ { ++ no_miso = <0>,"=3"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/spi0-1cs-overlay.dts b/arch/arm/boot/dts/overlays/spi0-1cs-overlay.dts new file mode 100644 index 000000000000..e6eb66e2076a @@ -31615,10 +33568,10 @@ index 000000000000..047695bb0c71 +}; diff --git a/arch/arm/boot/dts/overlays/tc358743-overlay.dts b/arch/arm/boot/dts/overlays/tc358743-overlay.dts new file mode 100644 -index 000000000000..a1f8af36d2e7 +index 000000000000..c3eebfd1f6ee --- /dev/null +++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts -@@ -0,0 +1,107 @@ +@@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Definitions for Toshiba TC358743 HDMI to CSI2 bridge on VC I2C bus +/dts-v1/; @@ -31627,23 +33580,23 @@ index 000000000000..a1f8af36d2e7 +/{ + compatible = "brcm,bcm2835"; + -+ fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + -+ tc358743@0f { ++ tc358743: tc358743@f { + compatible = "toshiba,tc358743"; + reg = <0x0f>; + status = "okay"; + -+ clocks = <&tc358743_clk>; ++ clocks = <&cam1_clk>; + clock-names = "refclk"; + + port { -+ tc358743: endpoint { ++ tc358743_0: endpoint { + remote-endpoint = <&csi1_ep>; + clock-lanes = <0>; + clock-noncontinuous; @@ -31655,28 +33608,28 @@ index 000000000000..a1f8af36d2e7 + }; + }; + -+ fragment@1 { ++ csi_frag: fragment@1 { + target = <&csi1>; -+ __overlay__ { ++ csi: __overlay__ { + status = "okay"; + + port { + csi1_ep: endpoint { -+ remote-endpoint = <&tc358743>; ++ remote-endpoint = <&tc358743_0>; + }; + }; + }; + }; + + fragment@2 { -+ target = <&tc358743>; ++ target = <&tc358743_0>; + __overlay__ { + data-lanes = <1 2>; + }; + }; + + fragment@3 { -+ target = <&tc358743>; ++ target = <&tc358743_0>; + __dormant__ { + data-lanes = <1 2 3 4>; + }; @@ -31696,14 +33649,11 @@ index 000000000000..a1f8af36d2e7 + }; + }; + -+ fragment@6 { -+ target-path = "/"; ++ clk_frag: fragment@6 { ++ target = <&cam1_clk>; + __overlay__ { -+ tc358743_clk: bridge-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <27000000>; -+ }; ++ status = "okay"; ++ clock-frequency = <27000000>; + }; + }; + @@ -31723,7 +33673,12 @@ index 000000000000..a1f8af36d2e7 + + __overrides__ { + 4lane = <0>, "-2+3-7+8"; -+ link-frequency = <&tc358743>,"link-frequencies#0"; ++ link-frequency = <&tc358743_0>,"link-frequencies#0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&tc358743>, "clocks:0=",<&cam0_clk>; + }; +}; diff --git a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts @@ -32409,11 +34364,11 @@ index 000000000000..fc8d9b118068 +}; diff --git a/arch/arm/boot/dts/overlays/upstream-overlay.dts b/arch/arm/boot/dts/overlays/upstream-overlay.dts new file mode 100644 -index 000000000000..7c4071a7cb27 +index 000000000000..2852bea52309 --- /dev/null +++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts @@ -0,0 +1,101 @@ -+// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-default dwc2-overlay.dts,dr_mode=otg ++// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-default,composite dwc2-overlay.dts,dr_mode=otg + +/dts-v1/; +/plugin/; @@ -32753,31 +34708,180 @@ index 000000000000..7792ead0cbb3 + }; + }; +}; -diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dpi-at056tn53v1-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dpi-at056tn53v1-overlay.dts +diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts new file mode 100644 -index 000000000000..f7181c9828bf +index 000000000000..1e5c5080592b --- /dev/null -+++ b/arch/arm/boot/dts/overlays/vc4-kms-dpi-at056tn53v1-overlay.dts -@@ -0,0 +1,44 @@ ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts +@@ -0,0 +1,74 @@ +/* -+ * vc4-kms-dpi-at056tn53v1-overlay.dts ++ * vc4-kms-dpi-generic-overlay.dts + */ + +/dts-v1/; +/plugin/; + -+#include -+#include ++#include "vc4-kms-dpi.dtsi" ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&panel>; ++ __overlay__ { ++ compatible = "panel-dpi"; ++ ++ width-mm = <154>; ++ height-mm = <83>; ++ bus-format = <0x1009>; ++ ++ timing: panel-timing { ++ clock-frequency = <29500000>; ++ hactive = <800>; ++ hfront-porch = <24>; ++ hsync-len = <72>; ++ hback-porch = <96>; ++ hsync-active = <1>; ++ vactive = <480>; ++ vfront-porch = <3>; ++ vsync-len = <10>; ++ vback-porch = <7>; ++ vsync-active = <1>; ++ ++ de-active = <1>; ++ pixelclk-active = <1>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&dpi>; ++ __overlay__ { ++ pinctrl-0 = <&dpi_18bit_gpio0>; ++ }; ++ }; ++ ++ __overrides__ { ++ clock-frequency = <&timing>, "clock-frequency:0"; ++ hactive = <&timing>, "hactive:0"; ++ hfp = <&timing>, "hfront-porch:0"; ++ hsync = <&timing>, "hsync-len:0"; ++ hbp = <&timing>, "hback-porch:0"; ++ vactive = <&timing>, "vactive:0"; ++ vfp = <&timing>, "vfront-porch:0"; ++ vsync = <&timing>, "vsync-len:0"; ++ vbp = <&timing>, "vback-porch:0"; ++ hsync-invert = <&timing>, "hsync-active:0=0"; ++ vsync-invert = <&timing>, "vsync-active:0=0"; ++ de-invert = <&timing>, "de-active:0=0"; ++ pixclk-invert = <&timing>, "pixelclk-active:0=0"; ++ ++ width-mm = <&panel>, "width-mm:0"; ++ height-mm = <&panel>, "height-mm:0"; ++ ++ rgb565 = <&panel>, "bus-format:0=0x1017", ++ <&dpi_node>, "pinctrl-0:0=",<&dpi_16bit_gpio0>; ++ rgb666-padhi = <&panel>, "bus-format:0=0x1015", ++ <&dpi_node>, "pinctrl-0:0=",<&dpi_18bit_cpadhi_gpio0>; ++ rgb888 = <&panel>, "bus-format:0=0x100a", ++ <&dpi_node>, "pinctrl-0:0=",<&dpi_gpio0>; ++ bus-format = <&panel>, "bus-format:0"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dpi-panel-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dpi-panel-overlay.dts +new file mode 100644 +index 000000000000..ee9e2e8fd246 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dpi-panel-overlay.dts +@@ -0,0 +1,69 @@ ++/* ++ * vc4-kms-dpi-panel-overlay.dts ++ * Support for any predefined DPI panel. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include "vc4-kms-dpi.dtsi" + +/ { + compatible = "brcm,bcm2835"; + + fragment@0 { ++ target = <&panel>; ++ __dormant__ { ++ compatible = "innolux,at056tn53v1", "simple-panel"; ++ }; ++ }; ++ fragment@1 { ++ target = <&panel>; ++ __dormant__ { ++ compatible = "ontat,yx700wv03", "simple-panel"; ++ }; ++ }; ++ fragment@2 { ++ target = <&panel>; ++ __dormant__ { ++ compatible = "geekworm,mzp280", "simple-panel"; ++ }; ++ }; ++ ++ fragment@90 { ++ target = <&dpi>; ++ __dormant__ { ++ pinctrl-0 = <&dpi_18bit_cpadhi_gpio0>; ++ }; ++ }; ++ fragment@91 { ++ target = <&dpi>; ++ __dormant__ { ++ pinctrl-0 = <&dpi_18bit_gpio0>; ++ }; ++ }; ++ fragment@92 { ++ target = <&dpi>; ++ __dormant__ { ++ pinctrl-0 = <&dpi_gpio0>; ++ }; ++ }; ++ fragment@93 { ++ target = <&dpi>; ++ __dormant__ { ++ pinctrl-0 = <&dpi_16bit_cpadhi_gpio0>; ++ }; ++ }; ++ fragment@94 { ++ target = <&dpi>; ++ __dormant__ { ++ pinctrl-0 = <&dpi_16bit_gpio0>; ++ }; ++ }; ++ ++ __overrides__ { ++ at056tn53v1 = <0>, "+0+90"; ++ kippah-7inch = <0>, "+1+91"; ++ mzp280 = <0>, "+2+93"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dpi.dtsi b/arch/arm/boot/dts/overlays/vc4-kms-dpi.dtsi +new file mode 100644 +index 000000000000..f78fa48b19f9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dpi.dtsi +@@ -0,0 +1,111 @@ ++/* ++ * vc4-kms-dpi.dtsi ++ */ ++ ++#include ++#include ++ ++/ { ++ fragment@100 { + target-path = "/"; + __overlay__ { + panel: panel { -+ compatible = "innolux,at056tn53v1", "simple-panel"; -+ ++ rotation = <0>; + port { + panel_in: endpoint { + remote-endpoint = <&dpi_out>; @@ -32787,13 +34891,12 @@ index 000000000000..f7181c9828bf + }; + }; + -+ fragment@1 { ++ fragment@101 { + target = <&dpi>; -+ __overlay__ { ++ dpi_node: __overlay__ { + status = "okay"; + + pinctrl-names = "default"; -+ pinctrl-0 = <&dpi_18bit_cpadhi_gpio0>; + + port { + dpi_out: endpoint { @@ -32802,10 +34905,84 @@ index 000000000000..f7181c9828bf + }; + }; + }; ++ ++ fragment@102 { ++ target = <&panel>; ++ __dormant__ { ++ backlight = <&backlight>; ++ }; ++ }; ++ ++ fragment@103 { ++ target-path = "/"; ++ __dormant__ { ++ backlight: backlight { ++ compatible = "gpio-backlight"; ++ gpios = <&gpio 255 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ }; ++ ++ fragment@104 { ++ target = <&panel>; ++ __dormant__ { ++ backlight = <&backlight_pwm>; ++ }; ++ }; ++ ++ fragment@105 { ++ target-path = "/"; ++ __dormant__ { ++ backlight_pwm: backlight_pwm { ++ compatible = "pwm-backlight"; ++ brightness-levels = <0 6 8 12 16 24 32 40 48 64 96 128 160 192 224 255>; ++ default-brightness-level = <16>; ++ pwms = <&pwm 0 200000>; ++ }; ++ }; ++ }; ++ ++ fragment@106 { ++ target = <&pwm>; ++ __dormant__ { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ assigned-clock-rates = <1000000>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@107 { ++ target = <&gpio>; ++ __dormant__ { ++ pwm_pins: pwm_pins { ++ brcm,pins = <18>; ++ brcm,function = <2>; /* Alt5 */ ++ }; ++ }; ++ }; ++ ++ fragment@108 { ++ target = <&audio>; ++ __dormant__ { ++ brcm,disable-headphones; ++ }; ++ }; ++ ++ __overrides__ { ++ backlight-gpio = <0>, "+102+103", ++ <&backlight>, "gpios:4"; ++ backlight-pwm = <0>, "+104+105+106+107+108"; ++ backlight-pwm-chan = <&backlight_pwm>, "pwms:4"; ++ backlight-pwm-gpio = <&pwm_pins>, "brcm,pins:0"; ++ backlight-pwm-func = <&pwm_pins>, "brcm,function:0"; ++ backlight-def-brightness = <&backlight_pwm>, "default-brightness-level:0"; ++ rotate = <&panel>, "rotation:0"; ++ }; +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts new file mode 100644 -index 000000000000..ecd3bef3d65a +index 000000000000..5e1700d0367a --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts @@ -0,0 +1,118 @@ @@ -32924,7 +35101,7 @@ index 000000000000..ecd3bef3d65a + }; + + __overrides__ { -+ disable_touch = <0>, "-10-11-12-13"; ++ disable_touch = <0>, "-10-11-12"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dsi-lt070me05000-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dsi-lt070me05000-overlay.dts @@ -33074,56 +35251,39 @@ index 000000000000..5dcd0f2243e2 +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts new file mode 100644 -index 000000000000..b03394844abd +index 000000000000..4c1aa1c70158 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-kippah-7inch-overlay.dts -@@ -0,0 +1,43 @@ +@@ -0,0 +1,26 @@ +/* -+ * vc4-kms-v3d-overlay.dts ++ * vc4-kms-kippah-7inch-overlay.dts + */ + +/dts-v1/; +/plugin/; + -+#include ++#include "vc4-kms-dpi.dtsi" + +/ { + compatible = "brcm,bcm2835"; + + fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ panel: panel { -+ compatible = "ontat,yx700wv03", "simple-panel"; -+ -+ port { -+ panel_in: endpoint { -+ remote-endpoint = <&dpi_out>; -+ }; -+ }; -+ }; ++ target = <&panel>; ++ __overlay__ { ++ compatible = "ontat,yx700wv03", "simple-panel"; + }; + }; + + fragment@1 { + target = <&dpi>; + __overlay__ { -+ status = "okay"; -+ -+ pinctrl-names = "default"; + pinctrl-0 = <&dpi_18bit_gpio0>; -+ -+ port { -+ dpi_out: endpoint@0 { -+ remote-endpoint = <&panel_in>; -+ }; -+ }; + }; + }; +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts new file mode 100644 -index 000000000000..5a4efdeed663 +index 000000000000..351fc160e803 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts @@ -0,0 +1,123 @@ @@ -33218,7 +35378,7 @@ index 000000000000..5a4efdeed663 + + fragment@11 { + target = <&vec>; -+ __overlay__ { ++ __dormant__ { + status = "okay"; + }; + }; @@ -33245,14 +35405,14 @@ index 000000000000..5a4efdeed663 + }; + + __overrides__ { -+ audio = <0>,"!13", <0>,"=14"; -+ noaudio = <0>,"=13", <0>,"!14"; -+ nocomposite = <0>, "!11"; ++ audio = <0>,"!13"; ++ noaudio = <0>,"=13"; ++ composite = <0>, "=11"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts new file mode 100644 -index 000000000000..4285e12a4e53 +index 000000000000..76229cad7803 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts @@ -0,0 +1,197 @@ @@ -33438,7 +35598,7 @@ index 000000000000..4285e12a4e53 + __overrides__ { + audio = <0>,"!17"; + audio1 = <0>,"!18"; -+ noaudio = <0>,"=17", <0>,"=18", <0>,"!19"; ++ noaudio = <0>,"=17", <0>,"=18"; + composite = <0>, "!1", + <0>, "!2", + <0>, "!3", @@ -33595,6 +35755,30 @@ index 000000000000..a4968d180a5d + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/vl805-overlay.dts b/arch/arm/boot/dts/overlays/vl805-overlay.dts +new file mode 100644 +index 000000000000..81adf34b29f2 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vl805-overlay.dts +@@ -0,0 +1,18 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/ { ++ compatible = "brcm,bcm2711"; ++ ++ fragment@0 { ++ target-path = "pcie0/pci@0,0"; ++ __overlay__ { ++ usb@0,0 { ++ reg = <0 0 0 0 0>; ++ resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>; ++ }; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts b/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts new file mode 100644 index 000000000000..f44e325bc1f2 @@ -33898,10 +36082,10 @@ index 000000000000..289fa4dacdf1 +}; diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 000000000000..7b4c28badf91 +index 000000000000..f2074da8a80d --- /dev/null +++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1510 @@ +@@ -0,0 +1,1533 @@ +CONFIG_LOCALVERSION="-v7" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -34512,6 +36696,8 @@ index 000000000000..7b4c28badf91 +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m ++CONFIG_KEYBOARD_TCA6416=m ++CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_CAP11XX=m +# CONFIG_INPUT_MOUSE is not set @@ -35101,6 +37287,24 @@ index 000000000000..7b4c28badf91 +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +CONFIG_USB_GADGET=m ++CONFIG_USB_CONFIGFS=m ++CONFIG_USB_CONFIGFS_SERIAL=y ++CONFIG_USB_CONFIGFS_ACM=y ++CONFIG_USB_CONFIGFS_OBEX=y ++CONFIG_USB_CONFIGFS_NCM=y ++CONFIG_USB_CONFIGFS_ECM=y ++CONFIG_USB_CONFIGFS_ECM_SUBSET=y ++CONFIG_USB_CONFIGFS_RNDIS=y ++CONFIG_USB_CONFIGFS_EEM=y ++CONFIG_USB_CONFIGFS_MASS_STORAGE=y ++CONFIG_USB_CONFIGFS_F_LB_SS=y ++CONFIG_USB_CONFIGFS_F_FS=y ++CONFIG_USB_CONFIGFS_F_UAC1=y ++CONFIG_USB_CONFIGFS_F_UAC2=y ++CONFIG_USB_CONFIGFS_F_MIDI=y ++CONFIG_USB_CONFIGFS_F_HID=y ++CONFIG_USB_CONFIGFS_F_UVC=y ++CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_USB_ZERO=m +CONFIG_USB_AUDIO=m +CONFIG_USB_ETH=m @@ -35127,6 +37331,7 @@ index 000000000000..7b4c28badf91 +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_PCA963X=m ++CONFIG_LEDS_PWM=y +CONFIG_LEDS_IS31FL32XX=m +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y @@ -35140,6 +37345,7 @@ index 000000000000..7b4c28badf91 +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m ++CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_ACCESSIBILITY=y +CONFIG_SPEAKUP=m @@ -35248,6 +37454,7 @@ index 000000000000..7b4c28badf91 +CONFIG_CCS811=m +CONFIG_SENSIRION_SGP30=m +CONFIG_SPS30=m ++CONFIG_MAX30102=m +CONFIG_DHT11=m +CONFIG_HDC100X=m +CONFIG_HTU21=m @@ -35414,10 +37621,10 @@ index 000000000000..7b4c28badf91 +# CONFIG_UPROBE_EVENTS is not set diff --git a/arch/arm/configs/bcm2711_defconfig b/arch/arm/configs/bcm2711_defconfig new file mode 100644 -index 000000000000..a4543d42fc55 +index 000000000000..8f4ae82cade4 --- /dev/null +++ b/arch/arm/configs/bcm2711_defconfig -@@ -0,0 +1,1550 @@ +@@ -0,0 +1,1557 @@ +CONFIG_LOCALVERSION="-v7l" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -36041,6 +38248,8 @@ index 000000000000..a4543d42fc55 +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m ++CONFIG_KEYBOARD_TCA6416=m ++CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_CAP11XX=m +# CONFIG_INPUT_MOUSE is not set @@ -36371,6 +38580,7 @@ index 000000000000..a4543d42fc55 +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_UDL=m +CONFIG_DRM_PANEL_SIMPLE=m ++CONFIG_DRM_PANEL_ILITEK_ILI9881C=m +CONFIG_DRM_PANEL_JDI_LT070ME05000=m +CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m +CONFIG_DRM_DISPLAY_CONNECTOR=m @@ -36392,6 +38602,7 @@ index 000000000000..a4543d42fc55 +CONFIG_FB_SIMPLE=y +CONFIG_FB_SSD1307=m +CONFIG_FB_RPISENSE=m ++CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_RPI=m +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -36681,6 +38892,7 @@ index 000000000000..a4543d42fc55 +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_PCA963X=m ++CONFIG_LEDS_PWM=y +CONFIG_LEDS_IS31FL32XX=m +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y @@ -36694,6 +38906,7 @@ index 000000000000..a4543d42fc55 +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m ++CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_ACCESSIBILITY=y +CONFIG_SPEAKUP=m @@ -36802,6 +39015,7 @@ index 000000000000..a4543d42fc55 +CONFIG_CCS811=m +CONFIG_SENSIRION_SGP30=m +CONFIG_SPS30=m ++CONFIG_MAX30102=m +CONFIG_DHT11=m +CONFIG_HDC100X=m +CONFIG_HTU21=m @@ -36970,10 +39184,10 @@ index 000000000000..a4543d42fc55 +# CONFIG_UPROBE_EVENTS is not set diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 -index 000000000000..5f1bd057138d +index 000000000000..b3ea44509d98 --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1523 @@ +@@ -0,0 +1,1528 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y @@ -37578,6 +39792,8 @@ index 000000000000..5f1bd057138d +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m ++CONFIG_KEYBOARD_TCA6416=m ++CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_CAP11XX=m +# CONFIG_INPUT_MOUSE is not set @@ -38210,6 +40426,7 @@ index 000000000000..5f1bd057138d +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_PCA963X=m ++CONFIG_LEDS_PWM=y +CONFIG_LEDS_IS31FL32XX=m +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y @@ -38223,6 +40440,7 @@ index 000000000000..5f1bd057138d +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m ++CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_ACCESSIBILITY=y +CONFIG_SPEAKUP=m @@ -38331,6 +40549,7 @@ index 000000000000..5f1bd057138d +CONFIG_CCS811=m +CONFIG_SENSIRION_SGP30=m +CONFIG_SPS30=m ++CONFIG_MAX30102=m +CONFIG_DHT11=m +CONFIG_HDC100X=m +CONFIG_HTU21=m @@ -38621,10 +40840,10 @@ index 6c607c68f3ad..ba7fc0bc9a15 100644 + #endif diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index 476d1a15e669..7ff524ed07d6 100644 +index da2a9e5fc59b..5e13b677fadd 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h -@@ -507,6 +507,9 @@ do { \ +@@ -509,6 +509,9 @@ do { \ extern unsigned long __must_check arm_copy_from_user(void *to, const void __user *from, unsigned long n); @@ -39266,10 +41485,10 @@ index 000000000000..bf6e4edfc9d3 +ENDPROC(memcmp) diff --git a/arch/arm/lib/memcpy_rpi.S b/arch/arm/lib/memcpy_rpi.S new file mode 100644 -index 000000000000..30f8a9089a83 +index 000000000000..77a1dbe28a18 --- /dev/null +++ b/arch/arm/lib/memcpy_rpi.S -@@ -0,0 +1,61 @@ +@@ -0,0 +1,63 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd @@ -39299,6 +41518,8 @@ index 000000000000..30f8a9089a83 +*/ + +#include ++#include ++#include +#include "arm-mem.h" +#include "memcpymove.h" + @@ -39333,10 +41554,10 @@ index 000000000000..30f8a9089a83 +ENDPROC(mmiocpy) diff --git a/arch/arm/lib/memcpymove.h b/arch/arm/lib/memcpymove.h new file mode 100644 -index 000000000000..d8be5849c860 +index 000000000000..65a6e065a7f2 --- /dev/null +++ b/arch/arm/lib/memcpymove.h -@@ -0,0 +1,506 @@ +@@ -0,0 +1,488 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd @@ -39697,19 +41918,13 @@ index 000000000000..d8be5849c860 + LAST .req ip + OFF .req lr + -+ .cfi_startproc ++ UNWIND( .fnstart ) + + push {D, DAT1, DAT2, lr} ++ UNWIND( .fnend ) + -+ .cfi_def_cfa_offset 16 -+ .cfi_rel_offset D, 0 -+ .cfi_undefined S -+ .cfi_undefined N -+ .cfi_undefined DAT0 -+ .cfi_rel_offset DAT1, 4 -+ .cfi_rel_offset DAT2, 8 -+ .cfi_undefined LAST -+ .cfi_rel_offset lr, 12 ++ UNWIND( .fnstart ) ++ UNWIND( .save {D, DAT1, DAT2, lr} ) + + .if backwards + add D, D, N @@ -39725,17 +41940,11 @@ index 000000000000..d8be5849c860 + + /* Long case */ + push {DAT3, DAT4, DAT5, DAT6, DAT7} ++ UNWIND( .fnend ) + -+ .cfi_def_cfa_offset 36 -+ .cfi_rel_offset D, 20 -+ .cfi_rel_offset DAT1, 24 -+ .cfi_rel_offset DAT2, 28 -+ .cfi_rel_offset DAT3, 0 -+ .cfi_rel_offset DAT4, 4 -+ .cfi_rel_offset DAT5, 8 -+ .cfi_rel_offset DAT6, 12 -+ .cfi_rel_offset DAT7, 16 -+ .cfi_rel_offset lr, 32 ++ UNWIND( .fnstart ) ++ UNWIND( .save {D, DAT1, DAT2, lr} ) ++ UNWIND( .save {DAT3, DAT4, DAT5, DAT6, DAT7} ) + + /* Adjust N so that the decrement instruction can also test for + * inner loop termination. We want it to stop when there are @@ -39775,16 +41984,10 @@ index 000000000000..d8be5849c860 +156: memcpy_long_inner_loop backwards, 2 +157: memcpy_long_inner_loop backwards, 3 + -+ .cfi_def_cfa_offset 16 -+ .cfi_rel_offset D, 0 -+ .cfi_rel_offset DAT1, 4 -+ .cfi_rel_offset DAT2, 8 -+ .cfi_same_value DAT3 -+ .cfi_same_value DAT4 -+ .cfi_same_value DAT5 -+ .cfi_same_value DAT6 -+ .cfi_same_value DAT7 -+ .cfi_rel_offset lr, 12 ++ UNWIND( .fnend ) ++ ++ UNWIND( .fnstart ) ++ UNWIND( .save {D, DAT1, DAT2, lr} ) + +160: /* Medium case */ + preload_all backwards, 0, 0, S, N, DAT2, OFF @@ -39827,7 +42030,7 @@ index 000000000000..d8be5849c860 + memcpy_short_inner_loop backwards, 0 +140: memcpy_short_inner_loop backwards, 1 + -+ .cfi_endproc ++ UNWIND( .fnend ) + + .unreq D + .unreq S @@ -39845,10 +42048,10 @@ index 000000000000..d8be5849c860 +.endm diff --git a/arch/arm/lib/memmove_rpi.S b/arch/arm/lib/memmove_rpi.S new file mode 100644 -index 000000000000..8b0760c0904c +index 000000000000..5715dfd95859 --- /dev/null +++ b/arch/arm/lib/memmove_rpi.S -@@ -0,0 +1,61 @@ +@@ -0,0 +1,63 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd @@ -39878,6 +42081,8 @@ index 000000000000..8b0760c0904c +*/ + +#include ++#include ++#include +#include "arm-mem.h" +#include "memcpymove.h" + @@ -39912,10 +42117,10 @@ index 000000000000..8b0760c0904c +ENDPROC(memmove) diff --git a/arch/arm/lib/memset_rpi.S b/arch/arm/lib/memset_rpi.S new file mode 100644 -index 000000000000..e8469cecabc1 +index 000000000000..2a2d86759397 --- /dev/null +++ b/arch/arm/lib/memset_rpi.S -@@ -0,0 +1,128 @@ +@@ -0,0 +1,130 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd @@ -39970,8 +42175,6 @@ index 000000000000..e8469cecabc1 + */ +ENTRY(mmioset) +ENTRY(memset) -+ENTRY(__memset32) -+ENTRY(__memset64) + + S .req a1 + DAT0 .req a2 @@ -39981,10 +42184,14 @@ index 000000000000..e8469cecabc1 + DAT3 .req lr + + orr DAT0, DAT0, DAT0, lsl #8 -+ push {S, lr} + orr DAT0, DAT0, DAT0, lsl #16 ++ ++ENTRY(__memset32) + mov DAT1, DAT0 + ++ENTRY(__memset64) ++ push {S, lr} ++ + /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */ + cmp N, #31 + blo 170f @@ -40006,7 +42213,7 @@ index 000000000000..e8469cecabc1 + stmcsia S!, {DAT0, DAT1} +164: /* Delayed set up of DAT2 and DAT3 so we could use them as scratch registers above */ + mov DAT2, DAT0 -+ mov DAT3, DAT0 ++ mov DAT3, DAT1 + /* Now the inner loop of 16-byte stores */ +165: stmia S!, {DAT0, DAT1, DAT2, DAT3} + subs N, N, #16 @@ -40022,7 +42229,7 @@ index 000000000000..e8469cecabc1 + +170: /* Short case */ + mov DAT2, DAT0 -+ mov DAT3, DAT0 ++ mov DAT3, DAT1 + tst S, #3 + beq 174f +172: subs N, N, #1 @@ -40221,7 +42428,7 @@ index 106f83a5ea6d..b483e5713039 100644 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index ae790908fc74..822125c5707a 100644 +index 9b594ae98153..a77c495f8378 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -161,9 +161,12 @@ config ARCH_BCM2835 @@ -40408,7 +42615,7 @@ index f0f65eb073e4..868011801521 100644 1: #ifdef CONFIG_DMA_CACHE_RWFO diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S -index dc8f152f3556..536df5db66e4 100644 +index 830bbfb26ca5..097248743b4c 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -363,7 +363,8 @@ ENDPROC(v7_flush_kern_dcache_area) @@ -40432,7 +42639,7 @@ index dc8f152f3556..536df5db66e4 100644 sub r3, r2, #1 bic r0, r0, r3 diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S -index e2c743aa2eb2..726c103fe555 100644 +index d9f7dfe2a7ed..687d126d1c6c 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -334,6 +334,8 @@ ENTRY(\name\()_cache_fns) @@ -40485,34 +42692,6 @@ index a0618f3e6836..b3a2fce22eac 100644 ret lr ENTRY(cpu_v6_dcache_clean_area) -diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S -index a59ddfd7a179..5820720e5363 100644 ---- a/arch/arm/mm/proc-v7.S -+++ b/arch/arm/mm/proc-v7.S -@@ -303,7 +303,11 @@ __v7_ca17mp_setup: - 1: adr r0, __v7_setup_stack_ptr - ldr r12, [r0] - add r12, r12, r0 @ the local stack -+1: - stmia r12, {r1-r6, lr} @ v7_invalidate_l1 touches r0-r6 -+ ldr r0, [r12, #(6 * 4)] @ read back the return address -+ teq r0, lr @ confirm it is correct -+ bne 1b @ retrying if not - bl v7_invalidate_l1 - ldmia r12, {r1-r6, lr} - #ifdef CONFIG_SMP -@@ -489,7 +493,11 @@ __v7_setup: - adr r0, __v7_setup_stack_ptr - ldr r12, [r0] - add r12, r12, r0 @ the local stack -+1: - stmia r12, {r1-r6, lr} @ v7_invalidate_l1 touches r0-r6 -+ ldr r0, [r12, #(6 * 4)] @ read back the return address -+ teq r0, lr @ confirm it is correct -+ bne 1b @ retrying if not - bl v7_invalidate_l1 - ldmia r12, {r1-r6, lr} - diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 2cb355c1b5b7..1e2dcf81aefa 100644 --- a/arch/arm/vfp/vfpmodule.c @@ -40592,7 +42771,7 @@ index 2cb355c1b5b7..1e2dcf81aefa 100644 /* * Save the userland NEON/VFP state. Under UP, diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index dd6b7466fe28..2a7abe568db7 100644 +index c924fce750f1..eed51552be27 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -39,6 +39,7 @@ config ARCH_BCM2835 @@ -40614,10 +42793,10 @@ index 9b1170658d60..cc6c25629057 100644 + +subdir-y += overlays diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index cb7de8d99223..69809bf2f45d 100644 +index cb7de8d99223..7fe8ece41072 100644 --- a/arch/arm64/boot/dts/broadcom/Makefile +++ b/arch/arm64/boot/dts/broadcom/Makefile -@@ -1,9 +1,20 @@ +@@ -1,9 +1,23 @@ # SPDX-License-Identifier: GPL-2.0 -dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb \ - bcm2837-rpi-3-a-plus.dtb \ @@ -40625,6 +42804,8 @@ index cb7de8d99223..69809bf2f45d 100644 bcm2837-rpi-3-b.dtb \ bcm2837-rpi-3-b-plus.dtb \ bcm2837-rpi-cm3-io3.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-zero-2.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-zero-2-w.dtb +dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-2-b.dtb +dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb +dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb @@ -40632,6 +42813,7 @@ index cb7de8d99223..69809bf2f45d 100644 +dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb +dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb +dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4s.dtb subdir-y += northstar2 subdir-y += stingray @@ -40668,6 +42850,20 @@ index 000000000000..e1e13784cff6 +++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-cm3.dts @@ -0,0 +1 @@ +#include "../../../../arm/boot/dts/bcm2710-rpi-cm3.dts" +diff --git a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2-w.dts b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2-w.dts +new file mode 100644 +index 000000000000..4d34e0afd4cd +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2-w.dts +@@ -0,0 +1 @@ ++#include "../../../../arm/boot/dts/bcm2710-rpi-zero-2-w.dts" +diff --git a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2.dts b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2.dts +new file mode 100644 +index 000000000000..4d34e0afd4cd +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-zero-2.dts +@@ -0,0 +1 @@ ++#include "../../../../arm/boot/dts/bcm2710-rpi-zero-2-w.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts index d24c53682e44..bf69a4b0b172 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts @@ -40690,6 +42886,13 @@ index 000000000000..8064a58155f1 +++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4.dts @@ -0,0 +1 @@ +#include "../../../../arm/boot/dts/bcm2711-rpi-cm4.dts" +diff --git a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4s.dts b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4s.dts +new file mode 100644 +index 000000000000..28e0980a374b +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4s.dts +@@ -0,0 +1 @@ ++#include "../../../../arm/boot/dts/bcm2711-rpi-cm4s.dts" diff --git a/arch/arm64/boot/dts/broadcom/bcm283x-rpi-csi1-2lane.dtsi b/arch/arm64/boot/dts/broadcom/bcm283x-rpi-csi1-2lane.dtsi new file mode 120000 index 000000000000..e5c400284467 @@ -40716,10 +42919,10 @@ index 000000000000..ded08646b6f6 \ No newline at end of file diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig new file mode 100644 -index 000000000000..88fa0a35d802 +index 000000000000..75333e69ef74 --- /dev/null +++ b/arch/arm64/configs/bcm2711_defconfig -@@ -0,0 +1,1556 @@ +@@ -0,0 +1,1566 @@ +CONFIG_LOCALVERSION="-v8" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -41118,6 +43321,7 @@ index 000000000000..88fa0a35d802 +CONFIG_NET_ACT_CSUM=m +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m ++CONFIG_VSOCKETS=m +CONFIG_CGROUP_NET_PRIO=y +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y @@ -41227,6 +43431,7 @@ index 000000000000..88fa0a35d802 +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_NET_VRF=m ++CONFIG_VSOCKMON=m +CONFIG_BCMGENET=y +CONFIG_ENC28J60=m +CONFIG_QCA7000_SPI=m @@ -41338,6 +43543,8 @@ index 000000000000..88fa0a35d802 +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m ++CONFIG_KEYBOARD_TCA6416=m ++CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_CAP11XX=m +# CONFIG_INPUT_MOUSE is not set @@ -41674,6 +43881,7 @@ index 000000000000..88fa0a35d802 +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_UDL=m +CONFIG_DRM_PANEL_SIMPLE=m ++CONFIG_DRM_PANEL_ILITEK_ILI9881C=m +CONFIG_DRM_PANEL_JDI_LT070ME05000=m +CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m +CONFIG_DRM_DISPLAY_CONNECTOR=m @@ -41695,6 +43903,7 @@ index 000000000000..88fa0a35d802 +CONFIG_FB_SIMPLE=y +CONFIG_FB_SSD1307=m +CONFIG_FB_RPISENSE=m ++CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_RPI=m +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -41984,6 +44193,7 @@ index 000000000000..88fa0a35d802 +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_PCA963X=m ++CONFIG_LEDS_PWM=y +CONFIG_LEDS_IS31FL32XX=m +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y @@ -41997,6 +44207,7 @@ index 000000000000..88fa0a35d802 +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m ++CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_ACCESSIBILITY=y +CONFIG_SPEAKUP=m @@ -42049,6 +44260,7 @@ index 000000000000..88fa0a35d802 +CONFIG_UIO=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_VHOST_NET=m ++CONFIG_VHOST_VSOCK=m +CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y +CONFIG_STAGING=y +CONFIG_PRISM2_USB=m @@ -42108,6 +44320,7 @@ index 000000000000..88fa0a35d802 +CONFIG_CCS811=m +CONFIG_SENSIRION_SGP30=m +CONFIG_SPS30=m ++CONFIG_MAX30102=m +CONFIG_DHT11=m +CONFIG_HDC100X=m +CONFIG_HTU21=m @@ -42278,10 +44491,10 @@ index 000000000000..88fa0a35d802 +# CONFIG_UPROBE_EVENTS is not set diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig new file mode 100644 -index 000000000000..00352da73009 +index 000000000000..419813140a52 --- /dev/null +++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -0,0 +1,1402 @@ +@@ -0,0 +1,1411 @@ +CONFIG_LOCALVERSION="-v8" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -42676,6 +44889,7 @@ index 000000000000..00352da73009 +CONFIG_NET_ACT_CSUM=m +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m ++CONFIG_VSOCKETS=m +CONFIG_CGROUP_NET_PRIO=y +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y @@ -42775,6 +44989,7 @@ index 000000000000..00352da73009 +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_NET_VRF=m ++CONFIG_VSOCKMON=m +CONFIG_ENC28J60=m +CONFIG_QCA7000_SPI=m +CONFIG_QCA7000_UART=m @@ -42880,6 +45095,8 @@ index 000000000000..00352da73009 +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m ++CONFIG_KEYBOARD_TCA6416=m ++CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_CAP11XX=m +# CONFIG_INPUT_MOUSE is not set @@ -43169,6 +45386,7 @@ index 000000000000..00352da73009 +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FB_UDL=m ++CONFIG_FB_SIMPLE=y +CONFIG_FB_SSD1307=m +CONFIG_FB_RPISENSE=m +CONFIG_BACKLIGHT_RPI=m @@ -43408,6 +45626,7 @@ index 000000000000..00352da73009 +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_PCA963X=m ++CONFIG_LEDS_PWM=y +CONFIG_LEDS_IS31FL32XX=m +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y @@ -43421,6 +45640,7 @@ index 000000000000..00352da73009 +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m ++CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_ACCESSIBILITY=y +CONFIG_SPEAKUP=m @@ -43470,6 +45690,7 @@ index 000000000000..00352da73009 +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_UIO=m +CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_VHOST_VSOCK=m +CONFIG_STAGING=y +CONFIG_PRISM2_USB=m +CONFIG_R8712U=m @@ -43526,6 +45747,7 @@ index 000000000000..00352da73009 +CONFIG_CCS811=m +CONFIG_SENSIRION_SGP30=m +CONFIG_SPS30=m ++CONFIG_MAX30102=m +CONFIG_DHT11=m +CONFIG_HTU21=m +CONFIG_APDS9960=m @@ -43685,7 +45907,7 @@ index 000000000000..00352da73009 +CONFIG_SCHED_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig -index 5e7d86cf5dfa..73caaa8ceb96 100644 +index d025bafcce43..fe49aafae978 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1027,6 +1027,7 @@ CONFIG_ROCKCHIP_EFUSE=y @@ -43758,10 +45980,10 @@ index fb507d569922..cc52829d426a 100644 asmlinkage void aesbs_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c -index 7e88057269d5..989ea8fe49d0 100644 +index ab955c249f37..bdc8e8ab1d81 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c -@@ -182,10 +182,15 @@ static void __init register_insn_emulation(struct insn_emulation_ops *ops) +@@ -183,10 +183,15 @@ static void __init register_insn_emulation(struct insn_emulation_ops *ops) switch (ops->status) { case INSN_DEPRECATED: @@ -43778,7 +46000,7 @@ index 7e88057269d5..989ea8fe49d0 100644 case INSN_OBSOLETE: insn->current_mode = INSN_UNDEF; diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c -index 1b5ee494488a..a0ce6bd92713 100644 +index 0cd3453a6f41..bd3a9d0c7093 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -17,6 +17,7 @@ @@ -43789,7 +46011,7 @@ index 1b5ee494488a..a0ce6bd92713 100644 #include #include #include -@@ -137,6 +138,10 @@ static int c_show(struct seq_file *m, void *v) +@@ -141,6 +142,10 @@ static int c_show(struct seq_file *m, void *v) { int i, j; bool aarch32 = personality(current->personality) == PER_LINUX32; @@ -43800,7 +46022,7 @@ index 1b5ee494488a..a0ce6bd92713 100644 for_each_online_cpu(i) { struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); -@@ -197,6 +202,26 @@ static int c_show(struct seq_file *m, void *v) +@@ -201,6 +206,26 @@ static int c_show(struct seq_file *m, void *v) seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr)); } @@ -43827,6 +46049,25 @@ index 1b5ee494488a..a0ce6bd92713 100644 return 0; } +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 6efd981979bd..f704d3b65fe5 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -451,6 +451,14 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK }, + ++ /* Additional Realtek 8761B Bluetooth devices */ ++ { USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ ++ /* Additional Realtek 8761BU Bluetooth devices */ ++ { USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ + /* Additional Realtek 8821AE Bluetooth devices */ + { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK }, diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 996729e78105..6d179e455721 100644 --- a/drivers/bluetooth/hci_h5.c @@ -43842,7 +46083,7 @@ index 996729e78105..6d179e455721 100644 if (H5_HDR_LEN(hdr) > 2) h5->tx_win = (data[2] & 0x07); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 4f451477281b..ea3b07016882 100644 +index 6fa56a473995..6389eb91e04b 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -5,6 +5,8 @@ @@ -45457,7 +47698,7 @@ index 000000000000..ac314617229c +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rpi-vcio"); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 72676f6e2364..65b985197429 100644 +index 53e63d68ffb1..8888a116b49d 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -104,7 +104,7 @@ config HW_RANDOM_IPROC_RNG200 @@ -45647,7 +47888,7 @@ index da8fcf147eb1..f78099e1d9e7 100644 obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 1ac803e14fa3..39fabced602a 100644 +index b7f89873fcf5..36e110f963bc 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -35,6 +35,7 @@ @@ -45701,7 +47942,7 @@ index 1ac803e14fa3..39fabced602a 100644 } cprman_write(cprman, data->a2w_ctrl_reg, -@@ -1016,6 +1022,30 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, +@@ -1011,6 +1017,30 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); } @@ -45732,7 +47973,7 @@ index 1ac803e14fa3..39fabced602a 100644 static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock) { struct bcm2835_cprman *cprman = clock->cprman; -@@ -1074,8 +1104,10 @@ static int bcm2835_clock_on(struct clk_hw *hw) +@@ -1069,8 +1099,10 @@ static int bcm2835_clock_on(struct clk_hw *hw) return 0; } @@ -45745,7 +47986,7 @@ index 1ac803e14fa3..39fabced602a 100644 { struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct bcm2835_cprman *cprman = clock->cprman; -@@ -1085,15 +1117,24 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, +@@ -1080,15 +1112,24 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, spin_lock(&cprman->regs_lock); @@ -45778,7 +48019,7 @@ index 1ac803e14fa3..39fabced602a 100644 ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0; cprman_write(cprman, data->ctl_reg, ctl); -@@ -1104,6 +1145,12 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, +@@ -1099,6 +1140,12 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, return 0; } @@ -45791,7 +48032,7 @@ index 1ac803e14fa3..39fabced602a 100644 static bool bcm2835_clk_is_pllc(struct clk_hw *hw) { -@@ -1287,6 +1334,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = { +@@ -1282,6 +1329,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = { .unprepare = bcm2835_clock_off, .recalc_rate = bcm2835_clock_get_rate, .set_rate = bcm2835_clock_set_rate, @@ -45799,7 +48040,7 @@ index 1ac803e14fa3..39fabced602a 100644 .determine_rate = bcm2835_clock_determine_rate, .set_parent = bcm2835_clock_set_parent, .get_parent = bcm2835_clock_get_parent, -@@ -1304,7 +1352,7 @@ static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) +@@ -1299,7 +1347,7 @@ static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) */ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { .is_prepared = bcm2835_vpu_clock_is_on, @@ -45808,7 +48049,7 @@ index 1ac803e14fa3..39fabced602a 100644 .set_rate = bcm2835_clock_set_rate, .determine_rate = bcm2835_clock_determine_rate, .set_parent = bcm2835_clock_set_parent, -@@ -1312,6 +1360,8 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { +@@ -1307,6 +1355,8 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { .debug_init = bcm2835_clock_debug_init, }; @@ -45817,7 +48058,7 @@ index 1ac803e14fa3..39fabced602a 100644 static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, const void *data) { -@@ -1329,6 +1379,9 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, +@@ -1324,6 +1374,9 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, init.ops = &bcm2835_pll_clk_ops; init.flags = pll_data->flags | CLK_IGNORE_UNUSED; @@ -45827,7 +48068,7 @@ index 1ac803e14fa3..39fabced602a 100644 pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) return NULL; -@@ -1384,6 +1437,13 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, +@@ -1379,6 +1432,13 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, divider->div.hw.init = &init; divider->div.table = NULL; @@ -45841,7 +48082,7 @@ index 1ac803e14fa3..39fabced602a 100644 divider->cprman = cprman; divider->data = divider_data; -@@ -1437,6 +1497,15 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, +@@ -1432,6 +1492,15 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, init.name = clock_data->name; init.flags = clock_data->flags | CLK_IGNORE_UNUSED; @@ -45857,7 +48098,7 @@ index 1ac803e14fa3..39fabced602a 100644 /* * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate * rate changes on at least of the parents. -@@ -1448,7 +1517,6 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, +@@ -1443,7 +1512,6 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, init.ops = &bcm2835_vpu_clock_clk_ops; } else { init.ops = &bcm2835_clock_clk_ops; @@ -45865,7 +48106,7 @@ index 1ac803e14fa3..39fabced602a 100644 /* If the clock wasn't actually enabled at boot, it's not * critical. -@@ -1673,16 +1741,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { +@@ -1668,16 +1736,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .hold_mask = CM_PLLA_HOLDCORE, .fixed_divider = 1, .flags = CLK_SET_RATE_PARENT), @@ -45888,7 +48129,7 @@ index 1ac803e14fa3..39fabced602a 100644 [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV( SOC_ALL, .name = "plla_dsi0", -@@ -1983,14 +2047,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { +@@ -1978,14 +2042,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .int_bits = 6, .frac_bits = 0, .tcnt_mux = 3), @@ -45909,7 +48150,29 @@ index 1ac803e14fa3..39fabced602a 100644 /* * VPU clock. This doesn't have an enable bit, since it drives * the bus for everything else, and is special so it doesn't need -@@ -2216,6 +2278,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { +@@ -2147,21 +2209,6 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .frac_bits = 12, + .tcnt_mux = 28), + +- /* TV encoder clock. Only operating frequency is 108Mhz. */ +- [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( +- SOC_ALL, +- .name = "vec", +- .ctl_reg = CM_VECCTL, +- .div_reg = CM_VECDIV, +- .int_bits = 4, +- .frac_bits = 0, +- /* +- * Allow rate change propagation only on PLLH_AUX which is +- * assigned index 7 in the parent array. +- */ +- .set_rate_parent = BIT(7), +- .tcnt_mux = 29), +- + /* dsi clocks */ + [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK( + SOC_ALL, +@@ -2211,6 +2258,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .ctl_reg = CM_PERIICTL), }; @@ -45918,7 +48181,7 @@ index 1ac803e14fa3..39fabced602a 100644 /* * Permanently take a reference on the parent of the SDRAM clock. * -@@ -2235,6 +2299,21 @@ static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) +@@ -2230,6 +2279,21 @@ static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) return clk_prepare_enable(parent); } @@ -45940,7 +48203,7 @@ index 1ac803e14fa3..39fabced602a 100644 static int bcm2835_clk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; -@@ -2243,7 +2322,9 @@ static int bcm2835_clk_probe(struct platform_device *pdev) +@@ -2238,7 +2302,9 @@ static int bcm2835_clk_probe(struct platform_device *pdev) const struct bcm2835_clk_desc *desc; const size_t asize = ARRAY_SIZE(clk_desc_array); const struct cprman_plat_data *pdata; @@ -45950,7 +48213,7 @@ index 1ac803e14fa3..39fabced602a 100644 int ret; pdata = of_device_get_match_data(&pdev->dev); -@@ -2262,6 +2343,21 @@ static int bcm2835_clk_probe(struct platform_device *pdev) +@@ -2257,6 +2323,21 @@ static int bcm2835_clk_probe(struct platform_device *pdev) if (IS_ERR(cprman->regs)) return PTR_ERR(cprman->regs); @@ -45972,7 +48235,7 @@ index 1ac803e14fa3..39fabced602a 100644 memcpy(cprman->real_parent_names, cprman_parent_names, sizeof(cprman_parent_names)); of_clk_parent_fill(dev->of_node, cprman->real_parent_names, -@@ -2295,8 +2391,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) +@@ -2290,8 +2371,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) if (ret) return ret; @@ -45989,7 +48252,7 @@ index 1ac803e14fa3..39fabced602a 100644 } static const struct cprman_plat_data cprman_bcm2835_plat_data = { -@@ -2322,7 +2425,11 @@ static struct platform_driver bcm2835_clk_driver = { +@@ -2317,7 +2405,11 @@ static struct platform_driver bcm2835_clk_driver = { .probe = bcm2835_clk_probe, }; @@ -46003,10 +48266,26 @@ index 1ac803e14fa3..39fabced602a 100644 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("BCM2835 clock driver"); diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c -index f89b9cfc4309..94ce38a2d5aa 100644 +index 969227e2df21..cbe9dd4dd446 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c -@@ -97,7 +97,7 @@ static int raspberrypi_clock_property(struct rpi_firmware *firmware, +@@ -33,6 +33,7 @@ enum rpi_firmware_clk_id { + RPI_FIRMWARE_EMMC2_CLK_ID, + RPI_FIRMWARE_M2MC_CLK_ID, + RPI_FIRMWARE_PIXEL_BVB_CLK_ID, ++ RPI_FIRMWARE_VEC_CLK_ID, + RPI_FIRMWARE_NUM_CLK_ID, + }; + +@@ -51,6 +52,7 @@ static char *rpi_firmware_clk_names[] = { + [RPI_FIRMWARE_EMMC2_CLK_ID] = "emmc2", + [RPI_FIRMWARE_M2MC_CLK_ID] = "m2mc", + [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb", ++ [RPI_FIRMWARE_VEC_CLK_ID] = "vec", + }; + + #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) +@@ -97,7 +99,7 @@ static int raspberrypi_clock_property(struct rpi_firmware *firmware, struct raspberrypi_firmware_prop msg = { .id = cpu_to_le32(data->id), .val = cpu_to_le32(*val), @@ -46015,14 +48294,17 @@ index f89b9cfc4309..94ce38a2d5aa 100644 }; int ret; -@@ -271,6 +271,7 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, +@@ -276,7 +278,10 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, case RPI_FIRMWARE_CORE_CLK_ID: case RPI_FIRMWARE_M2MC_CLK_ID: case RPI_FIRMWARE_V3D_CLK_ID: + case RPI_FIRMWARE_HEVC_CLK_ID: case RPI_FIRMWARE_PIXEL_BVB_CLK_ID: ++ case RPI_FIRMWARE_VEC_CLK_ID: ++ case RPI_FIRMWARE_PIXEL_CLK_ID: hw = raspberrypi_clk_register(rpi, clks->parent, clks->id); + if (IS_ERR(hw)) diff --git a/drivers/clk/clk-allo-dac.c b/drivers/clk/clk-allo-dac.c new file mode 100644 index 000000000000..a9844cb9454b @@ -46696,7 +48978,7 @@ index 000000000000..9e2634465823 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:clk-hifiberry-dacpro"); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -index 61c78714c095..f4695bac4cec 100644 +index b355d3d40f63..2feb27ca78aa 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -77,12 +77,14 @@ struct clk_core { @@ -46727,7 +49009,7 @@ index 61c78714c095..f4695bac4cec 100644 /*** runtime pm ***/ static int clk_pm_runtime_get(struct clk_core *core) { -@@ -1308,6 +1316,8 @@ static int clk_core_determine_round_nolock(struct clk_core *core, +@@ -1325,6 +1333,8 @@ static int clk_core_determine_round_nolock(struct clk_core *core, if (!core) return 0; @@ -46736,7 +49018,7 @@ index 61c78714c095..f4695bac4cec 100644 /* * At this point, core protection will be disabled if * - if the provider is not protected at all -@@ -1413,10 +1423,14 @@ unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate) +@@ -1430,10 +1440,14 @@ unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate) { int ret; struct clk_rate_request req; @@ -46751,7 +49033,7 @@ index 61c78714c095..f4695bac4cec 100644 ret = clk_core_round_rate_nolock(hw->core, &req); if (ret) return 0; -@@ -1437,6 +1451,7 @@ EXPORT_SYMBOL_GPL(clk_hw_round_rate); +@@ -1454,6 +1468,7 @@ EXPORT_SYMBOL_GPL(clk_hw_round_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct clk_rate_request req; @@ -46759,7 +49041,7 @@ index 61c78714c095..f4695bac4cec 100644 int ret; if (!clk) -@@ -1450,6 +1465,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) +@@ -1467,6 +1482,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate); req.rate = rate; @@ -46769,7 +49051,7 @@ index 61c78714c095..f4695bac4cec 100644 ret = clk_core_round_rate_nolock(clk->core, &req); if (clk->exclusive_count) -@@ -1917,6 +1935,7 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, +@@ -1934,6 +1952,7 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, unsigned long new_rate; unsigned long min_rate; unsigned long max_rate; @@ -46777,7 +49059,7 @@ index 61c78714c095..f4695bac4cec 100644 int p_index = 0; long ret; -@@ -1931,6 +1950,9 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, +@@ -1948,6 +1967,9 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core, clk_core_get_boundaries(core, &min_rate, &max_rate); @@ -46787,7 +49069,7 @@ index 61c78714c095..f4695bac4cec 100644 /* find the closest rate and parent clk/rate */ if (clk_core_can_round(core)) { struct clk_rate_request req; -@@ -2135,6 +2157,7 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core, +@@ -2152,6 +2174,7 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core, { int ret, cnt; struct clk_rate_request req; @@ -46795,7 +49077,7 @@ index 61c78714c095..f4695bac4cec 100644 lockdep_assert_held(&prepare_lock); -@@ -2149,6 +2172,9 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core, +@@ -2166,6 +2189,9 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core, clk_core_get_boundaries(core, &req.min_rate, &req.max_rate); req.rate = req_rate; @@ -46805,7 +49087,7 @@ index 61c78714c095..f4695bac4cec 100644 ret = clk_core_round_rate_nolock(core, &req); /* restore the protection */ -@@ -2242,6 +2268,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) +@@ -2259,6 +2285,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) ret = clk_core_set_rate_nolock(clk->core, rate); @@ -46815,7 +49097,7 @@ index 61c78714c095..f4695bac4cec 100644 if (clk->exclusive_count) clk_core_rate_protect(clk->core); -@@ -2401,6 +2430,103 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate) +@@ -2424,6 +2453,103 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL_GPL(clk_set_max_rate); @@ -46919,7 +49201,7 @@ index 61c78714c095..f4695bac4cec 100644 /** * clk_get_parent - return the parent of a clk * @clk: the clk whose parent gets returned -@@ -3811,6 +3937,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) +@@ -3874,6 +4000,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) goto fail_parents; INIT_HLIST_HEAD(&core->clks); @@ -46928,10 +49210,10 @@ index 61c78714c095..f4695bac4cec 100644 /* * Don't call clk_hw_create_clk() here because that would pin the diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index f28bb2334e74..8fbac86be34c 100644 +index 9cd7a7d86ca5..ea6ea555bb97 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig -@@ -652,6 +652,10 @@ config UNIPHIER_XDMAC +@@ -696,6 +696,10 @@ config UNIPHIER_XDMAC UniPhier platform. This DMA controller can transfer data from memory to memory, memory to peripheral and peripheral to memory. @@ -46943,7 +49225,7 @@ index f28bb2334e74..8fbac86be34c 100644 tristate "APM X-Gene DMA support" depends on ARCH_XGENE || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile -index 948a8da05f8b..e543c69fa6b5 100644 +index 8928816a4f30..7c4e625709f9 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_AT_XDMAC) += at_xdmac.o @@ -48372,7 +50654,7 @@ index 1d965c1252ca..849e63bb426d 100644 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index d1300fc003ed..d4f77fa37d40 100644 +index c9401840422a..f6bd6d10716b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -193,6 +193,12 @@ config GPIO_BCM_XGS_IPROC @@ -48388,7 +50670,7 @@ index d1300fc003ed..d4f77fa37d40 100644 config GPIO_BRCMSTB tristate "BRCMSTB GPIO support" default y if (ARCH_BRCMSTB || BMIPS_GENERIC) -@@ -467,6 +473,14 @@ config GPIO_PMIC_EIC_SPRD +@@ -488,6 +494,14 @@ config GPIO_PMIC_EIC_SPRD help Say yes here to support Spreadtrum PMIC EIC device. @@ -48403,7 +50685,7 @@ index d1300fc003ed..d4f77fa37d40 100644 config GPIO_PXA bool "PXA GPIO support" depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST -@@ -1158,6 +1172,15 @@ config HTC_EGPIO +@@ -1179,6 +1193,15 @@ config HTC_EGPIO several HTC phones. It provides basic support for input pins, output pins, and irqs. @@ -48420,7 +50702,7 @@ index d1300fc003ed..d4f77fa37d40 100644 tristate "Janz VMOD-TTL Digital IO Module" depends on MFD_JANZ_CMODIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index 09dada80ac34..71dda8a5625d 100644 +index 1af147d8ad71..cb5a275692d5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio-aspeed-sgpio.o @@ -48439,7 +50721,7 @@ index 09dada80ac34..71dda8a5625d 100644 obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o -@@ -118,6 +120,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o +@@ -119,6 +121,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o @@ -50034,7 +52316,7 @@ index 000000000000..89f5d6b353ab +MODULE_AUTHOR("Dave Stevenson "); +MODULE_DESCRIPTION("PWM GPIO driver"); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c -index af5bb8fedfea..2bd26c985246 100644 +index 59d8affad343..2ab00355b37b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -51,6 +51,8 @@ @@ -50046,7 +52328,7 @@ index af5bb8fedfea..2bd26c985246 100644 /* Device and char device-related information */ static DEFINE_IDA(gpio_ida); static dev_t gpio_devt; -@@ -2444,8 +2446,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) +@@ -2463,8 +2465,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) value = !!value; /* GPIOs used for enabled IRQs shall not be set as output */ @@ -50057,7 +52339,7 @@ index af5bb8fedfea..2bd26c985246 100644 gpiod_err(desc, "%s: tried to set a GPIO tied to an IRQ as output\n", __func__); -@@ -3250,8 +3252,8 @@ int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset) +@@ -3279,8 +3281,8 @@ int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset) } /* To be valid for IRQ the line needs to be input or open drain */ @@ -50069,10 +52351,10 @@ index af5bb8fedfea..2bd26c985246 100644 "%s: tried to flag a GPIO set as output for IRQ\n", __func__); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig -index ca868271f4c4..74872b157233 100644 +index b37e6660dd4e..2a0b8f3658b0 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig -@@ -392,6 +392,8 @@ source "drivers/gpu/drm/tidss/Kconfig" +@@ -395,6 +395,8 @@ source "drivers/gpu/drm/tidss/Kconfig" source "drivers/gpu/drm/xlnx/Kconfig" @@ -50082,19 +52364,19 @@ index ca868271f4c4..74872b157233 100644 menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile -index 81569009f884..78dd8e12525d 100644 +index e9dd6847c9fa..cc9a1da9402b 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile -@@ -124,3 +124,4 @@ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ +@@ -125,3 +125,4 @@ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ obj-$(CONFIG_DRM_MCDE) += mcde/ obj-$(CONFIG_DRM_TIDSS) += tidss/ obj-y += xlnx/ +obj-y += gud/ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -index bc9df3f216f5..282ee57afe04 100644 +index 55ecc67592eb..c8fe42d1d17c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -4988,7 +4988,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc) +@@ -5026,7 +5026,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc) static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = dm_crtc_reset_state, .destroy = amdgpu_dm_crtc_destroy, @@ -50102,7 +52384,7 @@ index bc9df3f216f5..282ee57afe04 100644 .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, .atomic_duplicate_state = dm_crtc_duplicate_state, -@@ -5472,25 +5471,6 @@ static int fill_hdr_info_packet(const struct drm_connector_state *state, +@@ -5510,25 +5509,6 @@ static int fill_hdr_info_packet(const struct drm_connector_state *state, return 0; } @@ -50128,7 +52410,7 @@ index bc9df3f216f5..282ee57afe04 100644 static int amdgpu_dm_connector_atomic_check(struct drm_connector *conn, struct drm_atomic_state *state) -@@ -5506,7 +5486,7 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn, +@@ -5544,7 +5524,7 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn, if (!crtc) return 0; @@ -50137,7 +52419,7 @@ index bc9df3f216f5..282ee57afe04 100644 struct dc_info_packet hdr_infopacket; ret = fill_hdr_info_packet(new_con_state, &hdr_infopacket); -@@ -5601,17 +5581,19 @@ static void dm_update_crtc_active_planes(struct drm_crtc *crtc, +@@ -5639,17 +5619,19 @@ static void dm_update_crtc_active_planes(struct drm_crtc *crtc, } static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, @@ -50161,7 +52443,7 @@ index bc9df3f216f5..282ee57afe04 100644 WARN_ON(1); return ret; } -@@ -5622,8 +5604,8 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, +@@ -5660,8 +5642,8 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, * planes are disabled, which is not supported by the hardware. And there is legacy * userspace which stops using the HW cursor altogether in response to the resulting EINVAL. */ @@ -50172,7 +52454,7 @@ index bc9df3f216f5..282ee57afe04 100644 return -EINVAL; /* In some use cases, like reset, no stream is attached */ -@@ -6522,9 +6504,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, +@@ -6563,9 +6545,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, if (connector_type == DRM_MODE_CONNECTOR_HDMIA || connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP) { @@ -50183,7 +52465,7 @@ index bc9df3f216f5..282ee57afe04 100644 if (!aconnector->mst_port) drm_connector_attach_vrr_capable_property(&aconnector->base); -@@ -7774,7 +7754,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) +@@ -7815,7 +7795,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_old_crtc_state->abm_level; hdr_changed = @@ -50193,7 +52475,7 @@ index bc9df3f216f5..282ee57afe04 100644 if (!scaling_changed && !abm_changed && !hdr_changed) continue; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c -index 955a055bd980..4eccd24757b3 100644 +index d617e98afb76..935e351e8ec4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -24,6 +24,7 @@ @@ -50204,7 +52486,7 @@ index 955a055bd980..4eccd24757b3 100644 #include #include #include -@@ -252,8 +253,10 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) +@@ -264,8 +265,10 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) static struct drm_encoder * dm_mst_atomic_best_encoder(struct drm_connector *connector, @@ -50341,7 +52623,7 @@ index af67fefed38d..a3234bfb0917 100644 struct drm_pending_vblank_event *event = crtc->state->event; diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c -index 587d94798f5c..494075ddbef6 100644 +index af729094260c..b5928b52e279 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -46,7 +46,7 @@ static enum drm_mode_status malidp_crtc_mode_valid(struct drm_crtc *crtc, @@ -50420,7 +52702,7 @@ index 587d94798f5c..494075ddbef6 100644 return ret; } -@@ -506,7 +510,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc) +@@ -509,7 +513,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc) } static const struct drm_crtc_funcs malidp_crtc_funcs = { @@ -50503,7 +52785,7 @@ index a887b6a5f8bd..f10a063b338c 100644 .page_flip = drm_atomic_helper_page_flip, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c -index a3c2f76668ab..5697eba6c56b 100644 +index d27f2840b955..9f3b8152becd 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -751,24 +751,26 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -50559,7 +52841,7 @@ index a3c2f76668ab..5697eba6c56b 100644 struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); -@@ -894,7 +898,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc, +@@ -897,7 +901,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc, static const struct drm_crtc_funcs ast_crtc_funcs = { .reset = ast_crtc_reset, @@ -50626,11 +52908,26 @@ index ce246b96330b..c8471bd4abbb 100644 }; int atmel_hlcdc_crtc_create(struct drm_device *dev) +diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c +index c916f4b8907e..a63d6d238e3c 100644 +--- a/drivers/gpu/drm/bridge/panel.c ++++ b/drivers/gpu/drm/bridge/panel.c +@@ -79,6 +79,10 @@ static int panel_bridge_attach(struct drm_bridge *bridge, + return ret; + } + ++ /* set up connector's "panel orientation" property */ ++ drm_connector_set_panel_orientation(&panel_bridge->connector, ++ panel_bridge->panel->orientation); ++ + drm_connector_attach_encoder(&panel_bridge->connector, + bridge->encoder); + diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 0c79a9ba48bb..4c4fb4b52b7d 100644 +index 356c7d0bd035..27858141cd21 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -2395,21 +2395,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) +@@ -2403,21 +2403,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) return ret; } @@ -50652,7 +52949,7 @@ index 0c79a9ba48bb..4c4fb4b52b7d 100644 static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { -@@ -2423,7 +2408,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, +@@ -2431,7 +2416,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, if (!crtc) return 0; @@ -50661,7 +52958,7 @@ index 0c79a9ba48bb..4c4fb4b52b7d 100644 crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); -@@ -2492,8 +2477,7 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) +@@ -2500,8 +2485,7 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) drm_connector_attach_max_bpc_property(connector, 8, 16); if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe) @@ -50672,7 +52969,7 @@ index 0c79a9ba48bb..4c4fb4b52b7d 100644 drm_connector_attach_encoder(connector, hdmi->bridge.encoder); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c -index 8a871e5c3e26..95addc0070ac 100644 +index 7fc8e7000046..dce69bffb34c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -122,7 +122,8 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, @@ -50716,7 +53013,7 @@ index 8a871e5c3e26..95addc0070ac 100644 if (ret) { DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n", crtc->base.id, crtc->name); -@@ -1093,7 +1098,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) +@@ -1103,7 +1108,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) if (new_crtc_state->enable && funcs->prepare) funcs->prepare(crtc); else if (funcs->atomic_disable) @@ -50725,7 +53022,7 @@ index 8a871e5c3e26..95addc0070ac 100644 else if (funcs->disable) funcs->disable(crtc); else if (funcs->dpms) -@@ -1313,7 +1318,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, +@@ -1323,7 +1328,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, if (new_conn_state->writeback_job && new_conn_state->writeback_job->fb) { WARN_ON(connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK); @@ -50734,7 +53031,7 @@ index 8a871e5c3e26..95addc0070ac 100644 } } } -@@ -1358,7 +1363,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, +@@ -1368,7 +1373,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n", crtc->base.id, crtc->name); if (funcs->atomic_enable) @@ -50743,7 +53040,7 @@ index 8a871e5c3e26..95addc0070ac 100644 else if (funcs->commit) funcs->commit(crtc); } -@@ -2034,6 +2039,9 @@ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc) +@@ -2044,6 +2049,9 @@ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc) * should always call this function from their * &drm_mode_config_funcs.atomic_commit hook. * @@ -50753,7 +53050,7 @@ index 8a871e5c3e26..95addc0070ac 100644 * To be able to use this support drivers need to use a few more helper * functions. drm_atomic_helper_wait_for_dependencies() must be called before * actually committing the hardware state, and for nonblocking commits this call -@@ -2077,8 +2085,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, +@@ -2087,8 +2095,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_crtc_commit *commit; @@ -50765,7 +53062,7 @@ index 8a871e5c3e26..95addc0070ac 100644 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { commit = kzalloc(sizeof(*commit), GFP_KERNEL); if (!commit) -@@ -2155,6 +2166,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, +@@ -2165,6 +2176,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, new_plane_state->commit = drm_crtc_commit_get(commit); } @@ -50775,7 +53072,7 @@ index 8a871e5c3e26..95addc0070ac 100644 return 0; } EXPORT_SYMBOL(drm_atomic_helper_setup_commit); -@@ -2507,7 +2521,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, +@@ -2517,7 +2531,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (active_only && !new_crtc_state->active) continue; @@ -50784,7 +53081,7 @@ index 8a871e5c3e26..95addc0070ac 100644 } for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) { -@@ -2565,7 +2579,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, +@@ -2575,7 +2589,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (active_only && !new_crtc_state->active) continue; @@ -50793,7 +53090,7 @@ index 8a871e5c3e26..95addc0070ac 100644 } } EXPORT_SYMBOL(drm_atomic_helper_commit_planes); -@@ -2603,7 +2617,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) +@@ -2613,7 +2627,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) crtc_funcs = crtc->helper_private; if (crtc_funcs && crtc_funcs->atomic_begin) @@ -50802,7 +53099,7 @@ index 8a871e5c3e26..95addc0070ac 100644 drm_for_each_plane_mask(plane, crtc->dev, plane_mask) { struct drm_plane_state *old_plane_state = -@@ -2629,7 +2643,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) +@@ -2639,7 +2653,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) } if (crtc_funcs && crtc_funcs->atomic_flush) @@ -50811,7 +53108,7 @@ index 8a871e5c3e26..95addc0070ac 100644 } EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc); -@@ -3485,76 +3499,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, +@@ -3495,76 +3509,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); @@ -50889,7 +53186,7 @@ index 8a871e5c3e26..95addc0070ac 100644 * drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to * the input end of a bridge diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c -index 138ff34b31db..8c225fb7441d 100644 +index 138ff34b31db..78933e2a5f44 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -22,6 +22,7 @@ @@ -50922,7 +53219,7 @@ index 138ff34b31db..8c225fb7441d 100644 */ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, uint degamma_lut_size, -@@ -231,6 +228,102 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, +@@ -231,6 +228,105 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); @@ -51011,7 +53308,10 @@ index 138ff34b31db..8c225fb7441d 100644 + /* Set GAMMA_LUT and reset DEGAMMA_LUT and CTM */ + replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL); + replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); -+ replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob); ++ if (!crtc_state->gamma_lut || !crtc_state->gamma_lut->data || ++ memcmp(crtc_state->gamma_lut->data, blob_data, blob->length)) ++ replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob); ++ + crtc_state->color_mgmt_changed |= replaced; + + ret = drm_atomic_commit(state); @@ -51025,7 +53325,7 @@ index 138ff34b31db..8c225fb7441d 100644 /** * drm_mode_gamma_set_ioctl - set the gamma table * @dev: DRM device -@@ -262,7 +355,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, +@@ -262,7 +358,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, if (!crtc) return -ENOENT; @@ -51034,7 +53334,7 @@ index 138ff34b31db..8c225fb7441d 100644 return -ENOSYS; /* memcpy into gamma store */ -@@ -290,8 +383,8 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, +@@ -290,8 +386,8 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, goto out; } @@ -51046,7 +53346,7 @@ index 138ff34b31db..8c225fb7441d 100644 out: DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c -index 717c4e7271b0..c0beaa2ea6ee 100644 +index 5163433ac561..a0803ac21a43 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -94,6 +94,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { @@ -51133,6 +53433,52 @@ index 717c4e7271b0..c0beaa2ea6ee 100644 /** * drm_connector_set_vrr_capable_property - sets the variable refresh rate * capable property for a connector +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 4334e466b4e0..8ba175445a6b 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -4960,8 +4960,15 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, + connector->name, dc_bpc); + info->bpc = dc_bpc; + ++ /* ++ * Deep color support mandates RGB444 support for all video ++ * modes. ++ */ ++ info->color_formats |= DRM_COLOR_FORMAT_RGB444; ++ + /* YCRCB444 is optional according to spec. */ + if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) { ++ info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n", + connector->name); + } +@@ -5705,13 +5712,13 @@ static const u32 hdmi_colorimetry_val[] = { + #undef ACE + + /** +- * drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe +- * colorspace information ++ * drm_hdmi_avi_infoframe_colorimetry() - fill the HDMI AVI infoframe ++ * colorimetry information + * @frame: HDMI AVI infoframe + * @conn_state: connector state + */ + void +-drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, ++drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame, + const struct drm_connector_state *conn_state) + { + u32 colorimetry_val; +@@ -5730,7 +5737,7 @@ drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, + frame->extended_colorimetry = (colorimetry_val >> 2) & + EXTENDED_COLORIMETRY_MASK; + } +-EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace); ++EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorimetry); + + /** + * drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 722c7ebe4e88..bdc7c605f43e 100644 --- a/drivers/gpu/drm/drm_fourcc.c @@ -51174,6 +53520,44 @@ index 2f5b0c2bb0fe..89ced6af9c5c 100644 } if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) { +diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c +index f634371c717a..bee5066e9227 100644 +--- a/drivers/gpu/drm/drm_panel.c ++++ b/drivers/gpu/drm/drm_panel.c +@@ -61,6 +61,9 @@ void drm_panel_init(struct drm_panel *panel, struct device *dev, + panel->dev = dev; + panel->funcs = funcs; + panel->connector_type = connector_type; ++ ++ panel->orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; ++ of_drm_get_panel_orientation(dev->of_node, &panel->orientation); + } + EXPORT_SYMBOL(drm_panel_init); + +@@ -289,16 +292,18 @@ int of_drm_get_panel_orientation(const struct device_node *np, + if (ret < 0) + return ret; + +- if (rotation == 0) ++ if (rotation == 0) { + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; +- else if (rotation == 90) ++ } else if (rotation == 90) { + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; +- else if (rotation == 180) ++ } else if (rotation == 180) { + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; +- else if (rotation == 270) ++ } else if (rotation == 270) { + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; +- else ++ } else { ++ DRM_ERROR("%pOF: invalid orientation %d\n", np, ret); + return -EINVAL; ++ } + + return 0; + } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index e5432dcf6999..f8eb1061a55f 100644 --- a/drivers/gpu/drm/drm_probe_helper.c @@ -53818,7 +56202,7 @@ index 45c2556d6395..32f440223bd1 100644 .destroy = intel_crtc_destroy, \ .page_flip = drm_atomic_helper_page_flip, \ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c -index ecaa538b2d35..3e5558def1c5 100644 +index ef7878193491..2e2d14fcfbac 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -23,6 +23,7 @@ @@ -53846,9 +56230,18 @@ index ecaa538b2d35..3e5558def1c5 100644 return &intel_dp->mst_encoders[crtc->pipe]->base.base; } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c -index 1d616da4f165..bf4da68260b9 100644 +index 1d616da4f165..030b4d5ab829 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c +@@ -746,7 +746,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, + else + frame->colorspace = HDMI_COLORSPACE_RGB; + +- drm_hdmi_avi_infoframe_colorspace(frame, conn_state); ++ drm_hdmi_avi_infoframe_colorimetry(frame, conn_state); + + /* nonsense combination */ + drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range && @@ -2971,8 +2971,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c drm_connector_attach_content_type_property(connector); @@ -53912,7 +56305,7 @@ index 36abff0890b2..31267c00782f 100644 base); struct dcss_dev *dcss = dcss_crtc->base.dev->dev_private; diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c -index d412fc265395..7ebd99ee3240 100644 +index fd9d8e51837f..987fc13bca25 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -47,7 +47,7 @@ static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc) @@ -53968,10 +56361,10 @@ index d412fc265395..7ebd99ee3240 100644 spin_lock_irq(&crtc->dev->event_lock); if (crtc->state->event) { diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c -index b6bb5fc7d183..0f52e5f4aa2f 100644 +index e34718cf5c2e..b0a4bbb0b6c4 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c -@@ -112,7 +112,7 @@ static inline struct ingenic_drm *drm_crtc_get_priv(struct drm_crtc *crtc) +@@ -151,7 +151,7 @@ static int ingenic_drm_update_pixclk(struct notifier_block *nb, } static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, @@ -53980,7 +56373,7 @@ index b6bb5fc7d183..0f52e5f4aa2f 100644 { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); -@@ -126,7 +126,7 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -165,7 +165,7 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, } static void ingenic_drm_crtc_atomic_disable(struct drm_crtc *crtc, @@ -53989,7 +56382,7 @@ index b6bb5fc7d183..0f52e5f4aa2f 100644 { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); unsigned int var; -@@ -195,22 +195,27 @@ static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv, +@@ -234,22 +234,27 @@ static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv, } static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, @@ -54022,7 +56415,7 @@ index b6bb5fc7d183..0f52e5f4aa2f 100644 if (IS_ERR(ipu_state)) return PTR_ERR(ipu_state); -@@ -248,7 +253,7 @@ ingenic_drm_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode +@@ -287,7 +292,7 @@ ingenic_drm_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode } static void ingenic_drm_crtc_atomic_begin(struct drm_crtc *crtc, @@ -54031,7 +56424,7 @@ index b6bb5fc7d183..0f52e5f4aa2f 100644 { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); u32 ctrl = 0; -@@ -268,20 +273,20 @@ static void ingenic_drm_crtc_atomic_begin(struct drm_crtc *crtc, +@@ -307,16 +312,14 @@ static void ingenic_drm_crtc_atomic_begin(struct drm_crtc *crtc, } static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc, @@ -54046,10 +56439,14 @@ index b6bb5fc7d183..0f52e5f4aa2f 100644 - if (drm_atomic_crtc_needs_modeset(state)) { - ingenic_drm_crtc_update_timings(priv, &state->mode); +- priv->update_clk_rate = true; +- } + if (drm_atomic_crtc_needs_modeset(crtc_state)) { + ingenic_drm_crtc_update_timings(priv, &crtc_state->mode); - clk_set_rate(priv->pix_clk, state->adjusted_mode.clock * 1000); + if (priv->update_clk_rate) { + mutex_lock(&priv->clk_mutex); +@@ -326,7 +329,7 @@ static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc, } if (event) { @@ -54058,7 +56455,7 @@ index b6bb5fc7d183..0f52e5f4aa2f 100644 spin_lock_irq(&crtc->dev->event_lock); if (drm_crtc_vblank_get(crtc) == 0) -@@ -642,8 +647,6 @@ static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = { +@@ -687,8 +690,6 @@ static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = { .enable_vblank = ingenic_drm_enable_vblank, .disable_vblank = ingenic_drm_disable_vblank, @@ -54355,7 +56752,7 @@ index a0253297bc76..34e3186e236d 100644 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c -index 7d7668998501..baf9f1d550c6 100644 +index ff4f207cbdea..ee30ec6ad84d 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -7,6 +7,7 @@ @@ -54384,7 +56781,7 @@ index 7d7668998501..baf9f1d550c6 100644 { struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); -@@ -682,15 +683,17 @@ static enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc, +@@ -688,15 +689,17 @@ static enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc, } static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, @@ -54404,7 +56801,7 @@ index 7d7668998501..baf9f1d550c6 100644 bool cursor_plane = false; bool need_right_mixer = false; int cnt = 0, i; -@@ -699,7 +702,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, +@@ -705,7 +708,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, DBG("%s: check", crtc->name); @@ -54413,7 +56810,7 @@ index 7d7668998501..baf9f1d550c6 100644 if (!pstate->visible) continue; -@@ -731,7 +734,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, +@@ -737,7 +740,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, if (mode->hdisplay > hw_cfg->lm.max_width) need_right_mixer = true; @@ -54422,7 +56819,7 @@ index 7d7668998501..baf9f1d550c6 100644 if (ret) { DRM_DEV_ERROR(dev->dev, "couldn't assign mixers %d\n", ret); return ret; -@@ -744,7 +747,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, +@@ -750,7 +753,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, WARN_ON(cursor_plane && (pstates[cnt - 1].plane->type != DRM_PLANE_TYPE_CURSOR)); @@ -54431,7 +56828,7 @@ index 7d7668998501..baf9f1d550c6 100644 /* verify that there are not too many planes attached to crtc * and that we don't have conflicting mixer stages: -@@ -769,13 +772,13 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, +@@ -775,13 +778,13 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, } static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc, @@ -54523,7 +56920,7 @@ index c2d34c91e840..afd2736f040d 100644 struct drm_crtc *crtc = connector_state->crtc; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c -index 61826cac3061..5f4edb5a77e4 100644 +index be649d14f879..32f80b69f9a7 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -30,6 +30,7 @@ @@ -54643,6 +57040,316 @@ index 328a4a74f534..84101e27cfb7 100644 .atomic_duplicate_state = omap_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .atomic_set_property = omap_crtc_atomic_set_property, +diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +index 534dd7414d42..6e03d9b0be60 100644 +--- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c ++++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +@@ -1,6 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0 + /* + * Copyright (C) 2017-2018, Bootlin ++ * Copyright (C) 2021, Henson Li ++ * Copyright (C) 2021, Penk Chen + */ + + #include +@@ -42,6 +44,7 @@ struct ili9881c_desc { + const struct ili9881c_instr *init; + const size_t init_length; + const struct drm_display_mode *mode; ++ const unsigned flags; + }; + + struct ili9881c { +@@ -453,6 +456,225 @@ static const struct ili9881c_instr k101_im2byl02_init[] = { + ILI9881C_COMMAND_INSTR(0xD3, 0x3F), /* VN0 */ + }; + ++static const struct ili9881c_instr nwe080_init[] = { ++ ILI9881C_SWITCH_PAGE_INSTR(3), ++ //GIP_1 ++ ILI9881C_COMMAND_INSTR(0x01, 0x00), ++ ILI9881C_COMMAND_INSTR(0x02, 0x00), ++ ILI9881C_COMMAND_INSTR(0x03, 0x73), ++ ILI9881C_COMMAND_INSTR(0x04, 0x00), ++ ILI9881C_COMMAND_INSTR(0x05, 0x00), ++ ILI9881C_COMMAND_INSTR(0x06, 0x0A), ++ ILI9881C_COMMAND_INSTR(0x07, 0x00), ++ ILI9881C_COMMAND_INSTR(0x08, 0x00), ++ ILI9881C_COMMAND_INSTR(0x09, 0x20), ++ ILI9881C_COMMAND_INSTR(0x0a, 0x20), ++ ILI9881C_COMMAND_INSTR(0x0b, 0x00), ++ ILI9881C_COMMAND_INSTR(0x0c, 0x00), ++ ILI9881C_COMMAND_INSTR(0x0d, 0x00), ++ ILI9881C_COMMAND_INSTR(0x0e, 0x00), ++ ILI9881C_COMMAND_INSTR(0x0f, 0x1E), ++ ILI9881C_COMMAND_INSTR(0x10, 0x1E), ++ ILI9881C_COMMAND_INSTR(0x11, 0x00), ++ ILI9881C_COMMAND_INSTR(0x12, 0x00), ++ ILI9881C_COMMAND_INSTR(0x13, 0x00), ++ ILI9881C_COMMAND_INSTR(0x14, 0x00), ++ ILI9881C_COMMAND_INSTR(0x15, 0x00), ++ ILI9881C_COMMAND_INSTR(0x16, 0x00), ++ ILI9881C_COMMAND_INSTR(0x17, 0x00), ++ ILI9881C_COMMAND_INSTR(0x18, 0x00), ++ ILI9881C_COMMAND_INSTR(0x19, 0x00), ++ ILI9881C_COMMAND_INSTR(0x1A, 0x00), ++ ILI9881C_COMMAND_INSTR(0x1B, 0x00), ++ ILI9881C_COMMAND_INSTR(0x1C, 0x00), ++ ILI9881C_COMMAND_INSTR(0x1D, 0x00), ++ ILI9881C_COMMAND_INSTR(0x1E, 0x40), ++ ILI9881C_COMMAND_INSTR(0x1F, 0x80), ++ ILI9881C_COMMAND_INSTR(0x20, 0x06), ++ ILI9881C_COMMAND_INSTR(0x21, 0x01), ++ ILI9881C_COMMAND_INSTR(0x22, 0x00), ++ ILI9881C_COMMAND_INSTR(0x23, 0x00), ++ ILI9881C_COMMAND_INSTR(0x24, 0x00), ++ ILI9881C_COMMAND_INSTR(0x25, 0x00), ++ ILI9881C_COMMAND_INSTR(0x26, 0x00), ++ ILI9881C_COMMAND_INSTR(0x27, 0x00), ++ ILI9881C_COMMAND_INSTR(0x28, 0x33), ++ ILI9881C_COMMAND_INSTR(0x29, 0x03), ++ ILI9881C_COMMAND_INSTR(0x2A, 0x00), ++ ILI9881C_COMMAND_INSTR(0x2B, 0x00), ++ ILI9881C_COMMAND_INSTR(0x2C, 0x00), ++ ILI9881C_COMMAND_INSTR(0x2D, 0x00), ++ ILI9881C_COMMAND_INSTR(0x2E, 0x00), ++ ILI9881C_COMMAND_INSTR(0x2F, 0x00), ++ ILI9881C_COMMAND_INSTR(0x30, 0x00), ++ ILI9881C_COMMAND_INSTR(0x31, 0x00), ++ ILI9881C_COMMAND_INSTR(0x32, 0x00), ++ ILI9881C_COMMAND_INSTR(0x33, 0x00), ++ ILI9881C_COMMAND_INSTR(0x34, 0x04), ++ ILI9881C_COMMAND_INSTR(0x35, 0x00), ++ ILI9881C_COMMAND_INSTR(0x36, 0x00), ++ ILI9881C_COMMAND_INSTR(0x37, 0x00), ++ ILI9881C_COMMAND_INSTR(0x38, 0x3C), ++ ILI9881C_COMMAND_INSTR(0x39, 0x00), ++ ILI9881C_COMMAND_INSTR(0x3A, 0x00), ++ ILI9881C_COMMAND_INSTR(0x3B, 0x00), ++ ILI9881C_COMMAND_INSTR(0x3C, 0x00), ++ ILI9881C_COMMAND_INSTR(0x3D, 0x00), ++ ILI9881C_COMMAND_INSTR(0x3E, 0x00), ++ ILI9881C_COMMAND_INSTR(0x3F, 0x00), ++ ILI9881C_COMMAND_INSTR(0x40, 0x00), ++ ILI9881C_COMMAND_INSTR(0x41, 0x00), ++ ILI9881C_COMMAND_INSTR(0x42, 0x00), ++ ILI9881C_COMMAND_INSTR(0x43, 0x00), ++ ILI9881C_COMMAND_INSTR(0x44, 0x00), ++ ++ ILI9881C_COMMAND_INSTR(0x50, 0x10), ++ ILI9881C_COMMAND_INSTR(0x51, 0x32), ++ ILI9881C_COMMAND_INSTR(0x52, 0x54), ++ ILI9881C_COMMAND_INSTR(0x53, 0x76), ++ ILI9881C_COMMAND_INSTR(0x54, 0x98), ++ ILI9881C_COMMAND_INSTR(0x55, 0xba), ++ ILI9881C_COMMAND_INSTR(0x56, 0x10), ++ ILI9881C_COMMAND_INSTR(0x57, 0x32), ++ ILI9881C_COMMAND_INSTR(0x58, 0x54), ++ ILI9881C_COMMAND_INSTR(0x59, 0x76), ++ ILI9881C_COMMAND_INSTR(0x5A, 0x98), ++ ILI9881C_COMMAND_INSTR(0x5B, 0xba), ++ ILI9881C_COMMAND_INSTR(0x5C, 0xdc), ++ ILI9881C_COMMAND_INSTR(0x5D, 0xfe), ++ ++ //GIP_3 ++ ILI9881C_COMMAND_INSTR(0x5E, 0x00), ++ ILI9881C_COMMAND_INSTR(0x5F, 0x01), ++ ILI9881C_COMMAND_INSTR(0x60, 0x00), ++ ILI9881C_COMMAND_INSTR(0x61, 0x15), ++ ILI9881C_COMMAND_INSTR(0x62, 0x14), ++ ILI9881C_COMMAND_INSTR(0x63, 0x0E), ++ ILI9881C_COMMAND_INSTR(0x64, 0x0F), ++ ILI9881C_COMMAND_INSTR(0x65, 0x0C), ++ ILI9881C_COMMAND_INSTR(0x66, 0x0D), ++ ILI9881C_COMMAND_INSTR(0x67, 0x06), ++ ILI9881C_COMMAND_INSTR(0x68, 0x02), ++ ILI9881C_COMMAND_INSTR(0x69, 0x02), ++ ILI9881C_COMMAND_INSTR(0x6A, 0x02), ++ ILI9881C_COMMAND_INSTR(0x6B, 0x02), ++ ILI9881C_COMMAND_INSTR(0x6C, 0x02), ++ ILI9881C_COMMAND_INSTR(0x6D, 0x02), ++ ILI9881C_COMMAND_INSTR(0x6E, 0x07), ++ ILI9881C_COMMAND_INSTR(0x6F, 0x02), ++ ILI9881C_COMMAND_INSTR(0x70, 0x02), ++ ILI9881C_COMMAND_INSTR(0x71, 0x02), ++ ILI9881C_COMMAND_INSTR(0x72, 0x02), ++ ILI9881C_COMMAND_INSTR(0x73, 0x02), ++ ILI9881C_COMMAND_INSTR(0x74, 0x02), ++ ++ ILI9881C_COMMAND_INSTR(0x75, 0x01), ++ ILI9881C_COMMAND_INSTR(0x76, 0x00), ++ ILI9881C_COMMAND_INSTR(0x77, 0x14), ++ ILI9881C_COMMAND_INSTR(0x78, 0x15), ++ ILI9881C_COMMAND_INSTR(0x79, 0x0E), ++ ILI9881C_COMMAND_INSTR(0x7A, 0x0F), ++ ILI9881C_COMMAND_INSTR(0x7B, 0x0C), ++ ILI9881C_COMMAND_INSTR(0x7C, 0x0D), ++ ILI9881C_COMMAND_INSTR(0x7D, 0x06), ++ ILI9881C_COMMAND_INSTR(0x7E, 0x02), ++ ILI9881C_COMMAND_INSTR(0x7F, 0x02), ++ ILI9881C_COMMAND_INSTR(0x80, 0x02), ++ ILI9881C_COMMAND_INSTR(0x81, 0x02), ++ ILI9881C_COMMAND_INSTR(0x82, 0x02), ++ ILI9881C_COMMAND_INSTR(0x83, 0x02), ++ ILI9881C_COMMAND_INSTR(0x84, 0x07), ++ ILI9881C_COMMAND_INSTR(0x85, 0x02), ++ ILI9881C_COMMAND_INSTR(0x86, 0x02), ++ ILI9881C_COMMAND_INSTR(0x87, 0x02), ++ ILI9881C_COMMAND_INSTR(0x88, 0x02), ++ ILI9881C_COMMAND_INSTR(0x89, 0x02), ++ ILI9881C_COMMAND_INSTR(0x8A, 0x02), ++ ++ ILI9881C_SWITCH_PAGE_INSTR(4), ++ ILI9881C_COMMAND_INSTR(0x6C, 0x15), ++ ILI9881C_COMMAND_INSTR(0x6E, 0x2A), ++ ++ //clamp 15V ++ ILI9881C_COMMAND_INSTR(0x6F, 0x35), ++ ILI9881C_COMMAND_INSTR(0x3A, 0x92), ++ ILI9881C_COMMAND_INSTR(0x8D, 0x1F), ++ ILI9881C_COMMAND_INSTR(0x87, 0xBA), ++ ILI9881C_COMMAND_INSTR(0x26, 0x76), ++ ILI9881C_COMMAND_INSTR(0xB2, 0xD1), ++ ILI9881C_COMMAND_INSTR(0xB5, 0x27), ++ ILI9881C_COMMAND_INSTR(0x31, 0x75), ++ ILI9881C_COMMAND_INSTR(0x30, 0x03), ++ ILI9881C_COMMAND_INSTR(0x3B, 0x98), ++ ILI9881C_COMMAND_INSTR(0x35, 0x17), ++ ILI9881C_COMMAND_INSTR(0x33, 0x14), ++ ILI9881C_COMMAND_INSTR(0x38, 0x01), ++ ILI9881C_COMMAND_INSTR(0x39, 0x00), ++ ++ ILI9881C_SWITCH_PAGE_INSTR(1), ++ // direction rotate ++ //ILI9881C_COMMAND_INSTR(0x22, 0x0B), ++ ILI9881C_COMMAND_INSTR(0x22, 0x0A), ++ ILI9881C_COMMAND_INSTR(0x31, 0x00), ++ ILI9881C_COMMAND_INSTR(0x53, 0x63), ++ ILI9881C_COMMAND_INSTR(0x55, 0x69), ++ ILI9881C_COMMAND_INSTR(0x50, 0xC7), ++ ILI9881C_COMMAND_INSTR(0x51, 0xC2), ++ ILI9881C_COMMAND_INSTR(0x60, 0x26), ++ ++ ILI9881C_COMMAND_INSTR(0xA0, 0x08), ++ ILI9881C_COMMAND_INSTR(0xA1, 0x0F), ++ ILI9881C_COMMAND_INSTR(0xA2, 0x25), ++ ILI9881C_COMMAND_INSTR(0xA3, 0x01), ++ ILI9881C_COMMAND_INSTR(0xA4, 0x23), ++ ILI9881C_COMMAND_INSTR(0xA5, 0x18), ++ ILI9881C_COMMAND_INSTR(0xA6, 0x11), ++ ILI9881C_COMMAND_INSTR(0xA7, 0x1A), ++ ILI9881C_COMMAND_INSTR(0xA8, 0x81), ++ ILI9881C_COMMAND_INSTR(0xA9, 0x19), ++ ILI9881C_COMMAND_INSTR(0xAA, 0x26), ++ ILI9881C_COMMAND_INSTR(0xAB, 0x7C), ++ ILI9881C_COMMAND_INSTR(0xAC, 0x24), ++ ILI9881C_COMMAND_INSTR(0xAD, 0x1E), ++ ILI9881C_COMMAND_INSTR(0xAE, 0x5C), ++ ILI9881C_COMMAND_INSTR(0xAF, 0x2A), ++ ILI9881C_COMMAND_INSTR(0xB0, 0x2B), ++ ILI9881C_COMMAND_INSTR(0xB1, 0x50), ++ ILI9881C_COMMAND_INSTR(0xB2, 0x5C), ++ ILI9881C_COMMAND_INSTR(0xB3, 0x39), ++ ++ ILI9881C_COMMAND_INSTR(0xC0, 0x08), ++ ILI9881C_COMMAND_INSTR(0xC1, 0x1F), ++ ILI9881C_COMMAND_INSTR(0xC2, 0x24), ++ ILI9881C_COMMAND_INSTR(0xC3, 0x1D), ++ ILI9881C_COMMAND_INSTR(0xC4, 0x04), ++ ILI9881C_COMMAND_INSTR(0xC5, 0x32), ++ ILI9881C_COMMAND_INSTR(0xC6, 0x24), ++ ILI9881C_COMMAND_INSTR(0xC7, 0x1F), ++ ILI9881C_COMMAND_INSTR(0xC8, 0x90), ++ ILI9881C_COMMAND_INSTR(0xC9, 0x20), ++ ILI9881C_COMMAND_INSTR(0xCA, 0x2C), ++ ILI9881C_COMMAND_INSTR(0xCB, 0x82), ++ ILI9881C_COMMAND_INSTR(0xCC, 0x19), ++ ILI9881C_COMMAND_INSTR(0xCD, 0x22), ++ ILI9881C_COMMAND_INSTR(0xCE, 0x4E), ++ ILI9881C_COMMAND_INSTR(0xCF, 0x28), ++ ILI9881C_COMMAND_INSTR(0xD0, 0x2D), ++ ILI9881C_COMMAND_INSTR(0xD1, 0x51), ++ ILI9881C_COMMAND_INSTR(0xD2, 0x5D), ++ ILI9881C_COMMAND_INSTR(0xD3, 0x39), ++ ++ ILI9881C_SWITCH_PAGE_INSTR(0), ++ //PWM ++ ILI9881C_COMMAND_INSTR(0x51, 0x0F), ++ ILI9881C_COMMAND_INSTR(0x52, 0xFF), ++ ILI9881C_COMMAND_INSTR(0x53, 0x2C), ++ ++ ILI9881C_COMMAND_INSTR(0x11, 0x00), ++ ILI9881C_COMMAND_INSTR(0x29, 0x00), ++ ILI9881C_COMMAND_INSTR(0x35, 0x00), ++}; ++ + static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel) + { + return container_of(panel, struct ili9881c, panel); +@@ -603,6 +825,23 @@ static const struct drm_display_mode k101_im2byl02_default_mode = { + .height_mm = 217, + }; + ++static const struct drm_display_mode nwe080_default_mode = { ++ .clock = 71750, ++ ++ .hdisplay = 800, ++ .hsync_start = 800 + 52, ++ .hsync_end = 800 + 52 + 8, ++ .htotal = 800 + 52 + 8 + 48, ++ ++ .vdisplay = 1280, ++ .vsync_start = 1280 + 16, ++ .vsync_end = 1280 + 16 + 6, ++ .vtotal = 1280 + 16 + 6 + 15, ++ ++ .width_mm = 107, ++ .height_mm = 170, ++}; ++ + static int ili9881c_get_modes(struct drm_panel *panel, + struct drm_connector *connector) + { +@@ -670,7 +909,7 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi) + + drm_panel_add(&ctx->panel); + +- dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE; ++ dsi->mode_flags = ctx->desc->flags; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->lanes = 4; + +@@ -691,18 +930,28 @@ static const struct ili9881c_desc lhr050h41_desc = { + .init = lhr050h41_init, + .init_length = ARRAY_SIZE(lhr050h41_init), + .mode = &lhr050h41_default_mode, ++ .flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE, + }; + + static const struct ili9881c_desc k101_im2byl02_desc = { + .init = k101_im2byl02_init, + .init_length = ARRAY_SIZE(k101_im2byl02_init), + .mode = &k101_im2byl02_default_mode, ++ .flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE, ++}; ++ ++static const struct ili9881c_desc nwe080_desc = { ++ .init = nwe080_init, ++ .init_length = ARRAY_SIZE(nwe080_init), ++ .mode = &nwe080_default_mode, ++ .flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_VIDEO, + }; + + static const struct of_device_id ili9881c_of_match[] = { + { .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc }, + { .compatible = "feixin,k101-im2byl02", .data = &k101_im2byl02_desc }, +- { } ++ { .compatible = "nwe,nwe080", .data = &nwe080_desc }, ++ {} + }; + MODULE_DEVICE_TABLE(of, ili9881c_of_match); + diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c index 733010b5e4f5..7fb4d98e166d 100644 --- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c @@ -54695,7 +57402,7 @@ index 733010b5e4f5..7fb4d98e166d 100644 return ret; } diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c -index bbdd086be7f5..3f0c11fa60a5 100644 +index 4b92c6341490..3f0c11fa60a5 100644 --- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c @@ -219,7 +219,35 @@ static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel) @@ -54735,21 +57442,8 @@ index bbdd086be7f5..3f0c11fa60a5 100644 } static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts, -@@ -229,7 +257,7 @@ static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts, - - ret = i2c_smbus_write_byte_data(ts->i2c, reg, val); - if (ret) -- dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret); -+ dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret); - } - - static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) -@@ -265,15 +293,17 @@ static int rpi_touchscreen_noop(struct drm_panel *panel) - return 0; - } - --static int rpi_touchscreen_enable(struct drm_panel *panel) -+static int rpi_touchscreen_prepare(struct drm_panel *panel) +@@ -268,12 +296,14 @@ static int rpi_touchscreen_noop(struct drm_panel *panel) + static int rpi_touchscreen_prepare(struct drm_panel *panel) { struct rpi_touchscreen *ts = panel_to_ts(panel); - int i; @@ -54765,34 +57459,93 @@ index bbdd086be7f5..3f0c11fa60a5 100644 break; } -@@ -295,6 +325,13 @@ static int rpi_touchscreen_enable(struct drm_panel *panel) - rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); - msleep(100); - -+ return 0; -+} -+ -+static int rpi_touchscreen_enable(struct drm_panel *panel) -+{ -+ struct rpi_touchscreen *ts = panel_to_ts(panel); -+ - /* Turn on the backlight. */ - rpi_touchscreen_i2c_write(ts, REG_PWM, 255); - -@@ -349,7 +386,7 @@ static int rpi_touchscreen_get_modes(struct drm_panel *panel, - static const struct drm_panel_funcs rpi_touchscreen_funcs = { - .disable = rpi_touchscreen_disable, - .unprepare = rpi_touchscreen_noop, -- .prepare = rpi_touchscreen_noop, -+ .prepare = rpi_touchscreen_prepare, - .enable = rpi_touchscreen_enable, - .get_modes = rpi_touchscreen_get_modes, - }; diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c -index 204674fccd64..8becb0e31814 100644 +index b7b37082a9d7..860d3a784665 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c -@@ -2093,6 +2093,38 @@ static const struct panel_desc innolux_at043tn24 = { +@@ -112,8 +112,6 @@ struct panel_simple { + struct gpio_desc *hpd_gpio; + + struct drm_display_mode override_mode; +- +- enum drm_panel_orientation orientation; + }; + + static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) +@@ -373,9 +371,6 @@ static int panel_simple_get_modes(struct drm_panel *panel, + /* add hard-coded panel modes */ + num += panel_simple_get_non_edid_modes(p, connector); + +- /* set up connector's "panel orientation" property */ +- drm_connector_set_panel_orientation(connector, p->orientation); +- + return num; + } + +@@ -438,6 +433,7 @@ static int panel_dpi_probe(struct device *dev, + + of_property_read_u32(np, "width-mm", &desc->size.width); + of_property_read_u32(np, "height-mm", &desc->size.height); ++ of_property_read_u32(np, "bus-format", &desc->bus_format); + + /* Extract bus_flags from display_timing */ + bus_flags = 0; +@@ -447,6 +443,8 @@ static int panel_dpi_probe(struct device *dev, + + /* We do not know the connector for the DT node, so guess it */ + desc->connector_type = DRM_MODE_CONNECTOR_DPI; ++ /* Likewise for the bit depth. */ ++ desc->bpc = 8; + + panel->desc = desc; + +@@ -537,12 +535,6 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) + return err; + } + +- err = of_drm_get_panel_orientation(dev->of_node, &panel->orientation); +- if (err) { +- dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err); +- return err; +- } +- + ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); + if (ddc) { + panel->ddc = of_find_i2c_adapter_by_node(ddc); +@@ -1940,6 +1932,32 @@ static const struct panel_desc friendlyarm_hd702e = { + }, + }; + ++static const struct drm_display_mode geekworm_mzp280_mode = { ++ .clock = 32000, ++ .hdisplay = 480, ++ .hsync_start = 480 + 41, ++ .hsync_end = 480 + 41 + 20, ++ .htotal = 480 + 41 + 20 + 60, ++ .vdisplay = 640, ++ .vsync_start = 640 + 5, ++ .vsync_end = 640 + 5 + 10, ++ .vtotal = 640 + 5 + 10 + 10, ++ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, ++}; ++ ++static const struct panel_desc geekworm_mzp280 = { ++ .modes = &geekworm_mzp280_mode, ++ .num_modes = 1, ++ .bpc = 6, ++ .size = { ++ .width = 47, ++ .height = 61, ++ }, ++ .bus_format = MEDIA_BUS_FMT_RGB565_1X24_CPADHI, ++ .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, ++ .connector_type = DRM_MODE_CONNECTOR_DPI, ++}; ++ + static const struct drm_display_mode giantplus_gpg482739qs5_mode = { + .clock = 9000, + .hdisplay = 480, +@@ -2094,6 +2112,38 @@ static const struct panel_desc innolux_at043tn24 = { .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, }; @@ -54831,7 +57584,7 @@ index 204674fccd64..8becb0e31814 100644 static const struct drm_display_mode innolux_at070tn92_mode = { .clock = 33333, .hdisplay = 800, -@@ -3187,6 +3219,31 @@ static const struct panel_desc qd43003c0_40 = { +@@ -3189,6 +3239,31 @@ static const struct panel_desc qd43003c0_40 = { .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; @@ -54863,7 +57616,17 @@ index 204674fccd64..8becb0e31814 100644 static const struct display_timing rocktech_rk070er9427_timing = { .pixelclock = { 26400000, 33300000, 46800000 }, .hactive = { 800, 800, 800 }, -@@ -4075,6 +4132,9 @@ static const struct of_device_id platform_of_match[] = { +@@ -4059,6 +4134,9 @@ static const struct of_device_id platform_of_match[] = { + }, { + .compatible = "friendlyarm,hd702e", + .data = &friendlyarm_hd702e, ++ }, { ++ .compatible = "geekworm,mzp280", ++ .data = &geekworm_mzp280, + }, { + .compatible = "giantplus,gpg482739qs5", + .data = &giantplus_gpg482739qs5 +@@ -4077,6 +4155,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "innolux,at043tn24", .data = &innolux_at043tn24, @@ -54873,7 +57636,7 @@ index 204674fccd64..8becb0e31814 100644 }, { .compatible = "innolux,at070tn92", .data = &innolux_at070tn92, -@@ -4204,6 +4264,9 @@ static const struct of_device_id platform_of_match[] = { +@@ -4206,6 +4287,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "qiaodian,qd43003c0-40", .data = &qd43003c0_40, @@ -54913,10 +57676,10 @@ index f22a1b776f4b..5c9e28fdb6ad 100644 qxl_crtc_update_monitors_config(crtc, "disable"); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -index 1b9738e44909..675ac27eb240 100644 +index 065604c5837d..41a2f8d3e992 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -@@ -682,20 +682,23 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) +@@ -688,20 +688,23 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) */ static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc, @@ -54944,7 +57707,7 @@ index 1b9738e44909..675ac27eb240 100644 struct rcar_du_encoder *renc; /* Skip the writeback encoder. */ -@@ -710,7 +713,7 @@ static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc, +@@ -716,7 +719,7 @@ static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc, } static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, @@ -54953,7 +57716,7 @@ index 1b9738e44909..675ac27eb240 100644 { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state); -@@ -745,8 +748,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -751,8 +754,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, } static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, @@ -54965,7 +57728,7 @@ index 1b9738e44909..675ac27eb240 100644 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(old_state); struct rcar_du_device *rcdu = rcrtc->dev; -@@ -774,7 +779,7 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, +@@ -780,7 +785,7 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, } static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, @@ -54974,7 +57737,7 @@ index 1b9738e44909..675ac27eb240 100644 { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); -@@ -803,7 +808,7 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, +@@ -809,7 +814,7 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, } static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, @@ -54983,7 +57746,7 @@ index 1b9738e44909..675ac27eb240 100644 { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct drm_device *dev = rcrtc->crtc.dev; -@@ -1133,7 +1138,6 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = { +@@ -1145,7 +1150,6 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = { .set_crc_source = rcar_du_crtc_set_crc_source, .verify_crc_source = rcar_du_crtc_verify_crc_source, .get_crc_sources = rcar_du_crtc_get_crc_sources, @@ -54992,7 +57755,7 @@ index 1b9738e44909..675ac27eb240 100644 /* ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index 0f23144491e4..5a108247ace4 100644 +index af98bfcde518..64c7b17e3c90 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -693,7 +693,7 @@ static void rockchip_drm_set_win_enabled(struct drm_crtc *crtc, bool enabled) @@ -55052,7 +57815,7 @@ index 0f23144491e4..5a108247ace4 100644 struct drm_atomic_state *old_state = old_crtc_state->state; struct drm_plane_state *old_plane_state, *new_plane_state; struct vop *vop = to_vop(crtc); -@@ -1634,7 +1642,6 @@ static const struct drm_crtc_funcs vop_crtc_funcs = { +@@ -1637,7 +1645,6 @@ static const struct drm_crtc_funcs vop_crtc_funcs = { .disable_vblank = vop_crtc_disable_vblank, .set_crc_source = vop_crtc_set_crc_source, .verify_crc_source = vop_crtc_verify_crc_source, @@ -55092,7 +57855,7 @@ index 6f37c104c46f..409795786f03 100644 struct drm_device *drm_dev = crtc->dev; struct sti_mixer *mixer = to_sti_mixer(crtc); diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c -index 62488ac14923..6f3b523e16e8 100644 +index 089c00a8e7d4..ef05b58eeac3 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -420,7 +420,7 @@ static void ltdc_crtc_update_clut(struct drm_crtc *crtc) @@ -55113,7 +57876,7 @@ index 62488ac14923..6f3b523e16e8 100644 { struct ltdc_device *ldev = crtc_to_ltdc(crtc); struct drm_device *ddev = crtc->dev; -@@ -625,7 +625,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) +@@ -629,7 +629,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) } static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc, @@ -55122,7 +57885,7 @@ index 62488ac14923..6f3b523e16e8 100644 { struct ltdc_device *ldev = crtc_to_ltdc(crtc); struct drm_device *ddev = crtc->dev; -@@ -742,7 +742,6 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = { +@@ -746,7 +746,6 @@ static const struct drm_crtc_funcs ltdc_crtc_funcs = { .enable_vblank = ltdc_crtc_enable_vblank, .disable_vblank = ltdc_crtc_disable_vblank, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, @@ -55582,7 +58345,7 @@ index 8a390738d65b..1372e913e765 100644 /* Virtual and DMA addresses of the single shared page table. */ diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c -index 182c586525eb..b4fb899a9409 100644 +index 64fe63c1938f..59a5e0f8fa3b 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -4,6 +4,7 @@ @@ -55804,20 +58567,37 @@ index d0163e18e9ca..8281a044834f 100644 vc4_gem.o \ vc4_hdmi.o \ diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index f4ccca922e44..59e10c37b740 100644 +index 79724fddfb4b..294105f1e012 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -279,19 +279,15 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, +@@ -279,19 +279,32 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, * allows drivers to push pixels to more than one encoder from the * same CRTC. */ -static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc) +struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, + struct drm_crtc_state *state) ++{ ++ struct drm_encoder *encoder; ++ ++ WARN_ON(hweight32(state->encoder_mask) > 1); ++ ++ drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) ++ return encoder; ++ ++ return NULL; ++} ++ ++#define drm_for_each_connector_mask(connector, dev, connector_mask) \ ++ list_for_each_entry((connector), &(dev)->mode_config.connector_list, head) \ ++ for_each_if ((connector_mask) & drm_connector_mask(connector)) ++ ++struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc, ++ struct drm_crtc_state *state) { -- struct drm_connector *connector; + struct drm_connector *connector; - struct drm_connector_list_iter conn_iter; -- + - drm_connector_list_iter_begin(crtc->dev, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { - if (connector->state->crtc == crtc) { @@ -55826,16 +58606,14 @@ index f4ccca922e44..59e10c37b740 100644 - } - } - drm_connector_list_iter_end(&conn_iter); -+ struct drm_encoder *encoder; -+ -+ WARN_ON(hweight32(state->encoder_mask) > 1); ++ WARN_ON(hweight32(state->connector_mask) > 1); + -+ drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) -+ return encoder; ++ drm_for_each_connector_mask(connector, crtc->dev, state->connector_mask) ++ return connector; return NULL; } -@@ -305,22 +301,29 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) +@@ -305,23 +318,29 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR); } @@ -55857,10 +58635,9 @@ index f4ccca922e44..59e10c37b740 100644 u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); -- u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; -+ bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; + bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; + bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC; -+ u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; + u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; u8 ppc = pv_data->pixels_per_clock; + + u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end; @@ -55870,20 +58647,9 @@ index f4ccca922e44..59e10c37b740 100644 bool debug_dump_regs = false; if (debug_dump_regs) { -@@ -344,48 +347,59 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) - VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc, - PV_HORZB_HACTIVE)); - -- CRTC_WRITE(PV_VERTA, -- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -- PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, -- PV_VERTA_VSYNC)); -- CRTC_WRITE(PV_VERTB, -- VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, -- PV_VERTB_VFP) | -- VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); -- +@@ -357,37 +376,59 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) + VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); + if (interlace) { + bool odd_field_first = false; + u32 field_delay = mode->htotal * pixel_rep / (2 * ppc); @@ -55906,7 +58672,7 @@ index f4ccca922e44..59e10c37b740 100644 + CRTC_WRITE(PV_VERTA_EVEN, - VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end - 1, +- mode->crtc_vsync_end, - PV_VERTA_VBP) | - VC4_SET_FIELD(mode->crtc_vsync_end - - mode->crtc_vsync_start, @@ -55931,7 +58697,7 @@ index f4ccca922e44..59e10c37b740 100644 PV_VCONTROL_CONTINUOUS | (is_dsi ? PV_VCONTROL_DSI : 0) | PV_VCONTROL_INTERLACE | -- VC4_SET_FIELD(mode->htotal * pixel_rep / 2, +- VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc), - PV_VCONTROL_ODD_DELAY)); - CRTC_WRITE(PV_VSYNCD_EVEN, 0); + (odd_field_first @@ -55944,6 +58710,7 @@ index f4ccca922e44..59e10c37b740 100644 CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS | (is_dsi ? PV_VCONTROL_DSI : 0)); ++ CRTC_WRITE(PV_VSYNCD_EVEN, 0); } + CRTC_WRITE(PV_VERTA, @@ -55956,7 +58723,7 @@ index f4ccca922e44..59e10c37b740 100644 if (is_dsi) CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); -@@ -420,9 +434,11 @@ static void require_hvs_enabled(struct drm_device *dev) +@@ -422,9 +463,11 @@ static void require_hvs_enabled(struct drm_device *dev) SCALER_DISPCTRL_ENABLE); } @@ -55970,7 +58737,7 @@ index f4ccca922e44..59e10c37b740 100644 struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct drm_device *dev = crtc->dev; -@@ -452,21 +468,40 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel) +@@ -454,21 +497,40 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel) mdelay(20); if (vc4_encoder && vc4_encoder->post_crtc_disable) @@ -56013,7 +58780,7 @@ index f4ccca922e44..59e10c37b740 100644 int channel; if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, -@@ -485,21 +520,37 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) +@@ -487,21 +549,37 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) if (channel < 0) return 0; @@ -56054,7 +58821,7 @@ index f4ccca922e44..59e10c37b740 100644 /* * Make sure we issue a vblank event after disabling the CRTC if -@@ -516,13 +567,18 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, +@@ -518,13 +596,18 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, } static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, @@ -56075,7 +58842,7 @@ index f4ccca922e44..59e10c37b740 100644 require_hvs_enabled(dev); /* Enable vblank irq handling before crtc is started otherwise -@@ -530,17 +586,17 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -532,17 +615,17 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, */ drm_crtc_vblank_on(crtc); @@ -56097,7 +58864,7 @@ index f4ccca922e44..59e10c37b740 100644 /* When feeding the transposer block the pixelvalve is unneeded and * should not be enabled. -@@ -549,7 +605,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -551,7 +634,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); if (vc4_encoder->post_crtc_enable) @@ -56106,7 +58873,7 @@ index f4ccca922e44..59e10c37b740 100644 } static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, -@@ -597,18 +653,36 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state, +@@ -599,18 +682,36 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state, } static int vc4_crtc_atomic_check(struct drm_crtc *crtc, @@ -56146,7 +58913,34 @@ index f4ccca922e44..59e10c37b740 100644 if (conn_state->crtc != crtc) continue; -@@ -695,6 +769,7 @@ struct vc4_async_flip_state { +@@ -645,14 +746,14 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) + struct drm_crtc *crtc = &vc4_crtc->base; + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); +- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); +- u32 chan = vc4_state->assigned_channel; ++ u32 chan = vc4_crtc->current_hvs_channel; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); ++ spin_lock(&vc4_crtc->irq_lock); + if (vc4_crtc->event && +- (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)) || +- vc4_state->feed_txp)) { ++ (vc4_crtc->current_dlist == HVS_READ(SCALER_DISPLACTX(chan)) || ++ vc4_crtc->feeds_txp)) { + drm_crtc_send_vblank_event(crtc, vc4_crtc->event); + vc4_crtc->event = NULL; + drm_crtc_vblank_put(crtc); +@@ -665,6 +766,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) + */ + vc4_hvs_unmask_underrun(dev, chan); + } ++ spin_unlock(&vc4_crtc->irq_lock); + spin_unlock_irqrestore(&dev->event_lock, flags); + } + +@@ -697,6 +799,7 @@ struct vc4_async_flip_state { struct drm_pending_vblank_event *event; struct vc4_seqno_cb cb; @@ -56154,7 +58948,7 @@ index f4ccca922e44..59e10c37b740 100644 }; /* Called when the V3D execution for the BO being flipped to is done, so that -@@ -743,6 +818,39 @@ vc4_async_page_flip_complete(struct vc4_seqno_cb *cb) +@@ -745,6 +848,39 @@ vc4_async_page_flip_complete(struct vc4_seqno_cb *cb) up(&vc4->async_modeset); } @@ -56194,7 +58988,7 @@ index f4ccca922e44..59e10c37b740 100644 /* Implements async (non-vblank-synced) page flips. * * The page flip ioctl needs to return immediately, so we grab the -@@ -813,8 +921,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, +@@ -815,8 +951,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, */ drm_atomic_set_fb_for_plane(plane->state, fb); @@ -56204,7 +58998,15 @@ index f4ccca922e44..59e10c37b740 100644 /* Driver takes ownership of state on successful async commit. */ return 0; -@@ -894,7 +1001,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { +@@ -843,7 +978,6 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) + return NULL; + + old_vc4_state = to_vc4_crtc_state(crtc->state); +- vc4_state->feed_txp = old_vc4_state->feed_txp; + vc4_state->margins = old_vc4_state->margins; + vc4_state->assigned_channel = old_vc4_state->assigned_channel; + +@@ -896,7 +1030,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { .reset = vc4_crtc_reset, .atomic_duplicate_state = vc4_crtc_duplicate_state, .atomic_destroy_state = vc4_crtc_destroy_state, @@ -56212,6 +59014,65 @@ index f4ccca922e44..59e10c37b740 100644 .enable_vblank = vc4_enable_vblank, .disable_vblank = vc4_disable_vblank, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, +@@ -905,6 +1038,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { + static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { + .mode_valid = vc4_crtc_mode_valid, + .atomic_check = vc4_crtc_atomic_check, ++ .atomic_begin = vc4_hvs_atomic_begin, + .atomic_flush = vc4_hvs_atomic_flush, + .atomic_enable = vc4_crtc_atomic_enable, + .atomic_disable = vc4_crtc_atomic_disable, +@@ -1079,25 +1213,43 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, + return PTR_ERR(primary_plane); + } + ++ spin_lock_init(&vc4_crtc->irq_lock); + drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, + crtc_funcs, NULL); + drm_crtc_helper_add(crtc, crtc_helper_funcs); + + if (!vc4->hvs->hvs5) { + drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); +- + drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); ++ } ++ + ++ if (!vc4->hvs->hvs5) { + /* We support CTM, but only for one CRTC at a time. It's therefore + * implemented as private driver state in vc4_kms, not here. + */ +- drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); +- } ++ drm_crtc_enable_color_mgmt(crtc, 0, true, 0); + +- for (i = 0; i < crtc->gamma_size; i++) { +- vc4_crtc->lut_r[i] = i; +- vc4_crtc->lut_g[i] = i; +- vc4_crtc->lut_b[i] = i; ++ /* Initialize the VC4 gamma LUTs */ ++ for (i = 0; i < crtc->gamma_size; i++) { ++ vc4_crtc->lut_r[i] = i; ++ vc4_crtc->lut_g[i] = i; ++ vc4_crtc->lut_b[i] = i; ++ } ++ } else { ++ /* Initialize the VC5 gamma PWL entries. Assume 12-bit pipeline, ++ * evenly spread over full range. ++ */ ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++) { ++ vc4_crtc->pwl_r[i] = ++ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); ++ vc4_crtc->pwl_g[i] = ++ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); ++ vc4_crtc->pwl_b[i] = ++ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); ++ vc4_crtc->pwl_a[i] = ++ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); ++ } + } + + return 0; diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index 4fbbf980a299..a95d88fea8d2 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -56238,33 +59099,109 @@ index 4fbbf980a299..a95d88fea8d2 100644 list_for_each_entry(entry, &vc4->debugfs_list, link) { drm_debugfs_create_files(&entry->info, 1, diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c -index a90f2545baee..dde2c6014748 100644 +index a90f2545baee..0d4fb6818d51 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c -@@ -165,10 +165,20 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) - dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2, - DPI_FORMAT); - break; -+ case MEDIA_BUS_FMT_BGR666_1X24_CPADHI: -+ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2, -+ DPI_FORMAT); -+ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER); -+ break; - case MEDIA_BUS_FMT_RGB666_1X18: +@@ -131,7 +131,7 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) + struct vc4_dpi *dpi = vc4_encoder->dpi; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector = NULL, *connector_scan; +- u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE; ++ u32 dpi_c = DPI_ENABLE; + int ret; + + /* Look up the connector attached to DPI so we can get the +@@ -148,49 +148,88 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) + } + drm_connector_list_iter_end(&conn_iter); + +- if (connector && connector->display_info.num_bus_formats) { +- u32 bus_format = connector->display_info.bus_formats[0]; +- +- switch (bus_format) { +- case MEDIA_BUS_FMT_RGB888_1X24: +- dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, +- DPI_FORMAT); +- break; +- case MEDIA_BUS_FMT_BGR888_1X24: +- dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, +- DPI_FORMAT); +- dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER); +- break; +- case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: +- dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2, +- DPI_FORMAT); +- break; +- case MEDIA_BUS_FMT_RGB666_1X18: ++ if (connector) { ++ if (connector->display_info.num_bus_formats) { ++ u32 bus_format = connector->display_info.bus_formats[0]; ++ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, ++ DPI_FORMAT); ++ break; ++ case MEDIA_BUS_FMT_BGR888_1X24: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, ++ DPI_FORMAT); ++ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, ++ DPI_ORDER); ++ break; ++ case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2, ++ DPI_FORMAT); ++ break; ++ case MEDIA_BUS_FMT_BGR666_1X24_CPADHI: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2, ++ DPI_FORMAT); ++ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, ++ DPI_ORDER); ++ break; ++ default: ++ DRM_ERROR("Unknown media bus format %d\n", ++ bus_format); ++ fallthrough; ++ case MEDIA_BUS_FMT_RGB666_1X18: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, ++ DPI_FORMAT); ++ break; ++ case MEDIA_BUS_FMT_BGR666_1X18: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, ++ DPI_FORMAT); ++ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, ++ DPI_ORDER); ++ break; ++ case MEDIA_BUS_FMT_RGB565_1X16: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_3, ++ DPI_FORMAT); ++ break; ++ case MEDIA_BUS_FMT_RGB565_1X24_CPADHI: ++ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_2, ++ DPI_FORMAT); ++ break; ++ } ++ } else { ++ /* Default to 18bit if no connector found. */ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, DPI_FORMAT); - break; -+ case MEDIA_BUS_FMT_BGR666_1X18: -+ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, -+ DPI_FORMAT); -+ dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER); -+ break; - case MEDIA_BUS_FMT_RGB565_1X16: - dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_3, - DPI_FORMAT); -@@ -178,8 +188,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) - break; +- break; +- case MEDIA_BUS_FMT_RGB565_1X16: +- dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_3, +- DPI_FORMAT); +- break; +- default: +- DRM_ERROR("Unknown media bus format %d\n", bus_format); +- break; ++ } ++ ++ if (connector->display_info.bus_flags & ++ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ++ dpi_c |= DPI_PIXEL_CLK_INVERT; ++ ++ if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW) ++ dpi_c |= DPI_OUTPUT_ENABLE_INVERT; } else { - /* Default to 24bit if no connector found. */ - dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, DPI_FORMAT); @@ -56272,9 +59209,35 @@ index a90f2545baee..dde2c6014748 100644 + dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, DPI_FORMAT); } - if (mode->flags & DRM_MODE_FLAG_NHSYNC) +- if (mode->flags & DRM_MODE_FLAG_NHSYNC) +- dpi_c |= DPI_HSYNC_INVERT; +- else if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) +- dpi_c |= DPI_HSYNC_DISABLE; ++ if (mode->flags & DRM_MODE_FLAG_CSYNC) { ++ if (mode->flags & DRM_MODE_FLAG_NCSYNC) ++ dpi_c |= DPI_OUTPUT_ENABLE_INVERT; ++ } else { ++ dpi_c |= DPI_OUTPUT_ENABLE_MODE; ++ ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ dpi_c |= DPI_HSYNC_INVERT; ++ else if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) ++ dpi_c |= DPI_HSYNC_DISABLE; + +- if (mode->flags & DRM_MODE_FLAG_NVSYNC) +- dpi_c |= DPI_VSYNC_INVERT; +- else if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) +- dpi_c |= DPI_VSYNC_DISABLE; ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) ++ dpi_c |= DPI_VSYNC_INVERT; ++ else if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) ++ dpi_c |= DPI_VSYNC_DISABLE; ++ } + + DPI_WRITE(DPI_C, dpi_c); + diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 839610f8092a..dec3620bc7c5 100644 +index 52426bc8edb8..dec3620bc7c5 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -36,6 +36,8 @@ @@ -56286,20 +59249,22 @@ index 839610f8092a..dec3620bc7c5 100644 #include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" -@@ -246,6 +248,28 @@ static void vc4_match_add_drivers(struct device *dev, +@@ -246,15 +248,28 @@ static void vc4_match_add_drivers(struct device *dev, } } +-static const struct of_device_id vc4_dma_range_matches[] = { +- { .compatible = "brcm,bcm2711-hvs" }, +const struct of_device_id vc4_dma_range_matches[] = { -+ { .compatible = "brcm,bcm2835-hvs" }, + { .compatible = "brcm,bcm2835-hvs" }, + { .compatible = "brcm,bcm2711-hvs" }, + { .compatible = "raspberrypi,rpi-firmware-kms" }, -+ { .compatible = "brcm,bcm2835-v3d" }, -+ { .compatible = "brcm,cygnus-v3d" }, -+ { .compatible = "brcm,vc4-v3d" }, -+ {} -+}; -+ + { .compatible = "brcm,bcm2835-v3d" }, + { .compatible = "brcm,cygnus-v3d" }, + { .compatible = "brcm,vc4-v3d" }, + {} + }; + +/* + * we need this helper function for determining presence of fkms + * before it's been bound @@ -56315,24 +59280,7 @@ index 839610f8092a..dec3620bc7c5 100644 static int vc4_drm_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); -@@ -263,6 +287,16 @@ static int vc4_drm_bind(struct device *dev) - vc4_drm_driver.driver_features &= ~DRIVER_RENDER; - of_node_put(node); - -+ node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches, -+ NULL); -+ if (node) { -+ ret = of_dma_configure(dev, node, true); -+ of_node_put(node); -+ -+ if (ret) -+ return ret; -+ } -+ - vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base); - if (IS_ERR(vc4)) - return PTR_ERR(vc4); -@@ -285,22 +319,43 @@ static int vc4_drm_bind(struct device *dev) +@@ -304,22 +319,43 @@ static int vc4_drm_bind(struct device *dev) if (ret) return ret; @@ -56383,7 +59331,7 @@ index 839610f8092a..dec3620bc7c5 100644 ret = drm_dev_register(drm, 0); if (ret < 0) -@@ -330,14 +385,24 @@ static const struct component_master_ops vc4_drm_ops = { +@@ -349,14 +385,24 @@ static const struct component_master_ops vc4_drm_ops = { .unbind = vc4_drm_unbind, }; @@ -56410,10 +59358,18 @@ index 839610f8092a..dec3620bc7c5 100644 }; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 9809c3a856c6..7c749e08cb0c 100644 +index 921463625d82..dd34de6e677b 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -74,12 +74,16 @@ struct vc4_perfmon { +@@ -19,6 +19,7 @@ + #include + + #include "uapi/drm/vc4_drm.h" ++#include "vc4_regs.h" + + struct drm_device; + struct drm_gem_object; +@@ -74,11 +75,16 @@ struct vc4_perfmon { struct vc4_dev { struct drm_device base; @@ -56424,14 +59380,13 @@ index 9809c3a856c6..7c749e08cb0c 100644 struct vc4_hvs *hvs; struct vc4_v3d *v3d; struct vc4_dpi *dpi; -- struct vc4_dsi *dsi1; struct vc4_vec *vec; struct vc4_txp *txp; + struct vc4_fkms *fkms; struct vc4_hang_state *hang_state; -@@ -201,9 +205,6 @@ struct vc4_dev { +@@ -200,9 +206,6 @@ struct vc4_dev { int power_refcount; @@ -56441,7 +59396,7 @@ index 9809c3a856c6..7c749e08cb0c 100644 /* Set to true when the load tracker is active. */ bool load_tracker_enabled; -@@ -325,6 +326,7 @@ struct vc4_hvs { +@@ -324,6 +327,7 @@ struct vc4_hvs { u32 __iomem *dlist; struct clk *core_clk; @@ -56449,7 +59404,7 @@ index 9809c3a856c6..7c749e08cb0c 100644 /* Memory manager for CRTCs to allocate space in the display * list. Units are dwords. -@@ -444,12 +446,12 @@ struct vc4_encoder { +@@ -443,12 +447,12 @@ struct vc4_encoder { enum vc4_encoder_type type; u32 clock_select; @@ -56467,17 +59422,97 @@ index 9809c3a856c6..7c749e08cb0c 100644 }; static inline struct vc4_encoder * -@@ -518,6 +520,9 @@ vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc) +@@ -479,6 +483,17 @@ struct vc4_pv_data { + + }; + ++struct vc5_gamma_entry { ++ u32 x_c_terms; ++ u32 grad_term; ++}; ++ ++#define VC5_HVS_SET_GAMMA_ENTRY(x, c, g) (struct vc5_gamma_entry){ \ ++ .x_c_terms = VC4_SET_FIELD((x), SCALER5_DSPGAMMA_OFF_X) | \ ++ VC4_SET_FIELD((c), SCALER5_DSPGAMMA_OFF_C), \ ++ .grad_term = (g) \ ++} ++ + struct vc4_crtc { + struct drm_crtc base; + struct platform_device *pdev; +@@ -488,13 +503,50 @@ struct vc4_crtc { + /* Timestamp at start of vblank irq - unaffected by lock delays. */ + ktime_t t_vblank; + +- u8 lut_r[256]; +- u8 lut_g[256]; +- u8 lut_b[256]; ++ union { ++ struct { /* VC4 gamma LUT */ ++ u8 lut_r[256]; ++ u8 lut_g[256]; ++ u8 lut_b[256]; ++ }; ++ struct { /* VC5 gamma PWL entries */ ++ struct vc5_gamma_entry pwl_r[SCALER5_DSPGAMMA_NUM_POINTS]; ++ struct vc5_gamma_entry pwl_g[SCALER5_DSPGAMMA_NUM_POINTS]; ++ struct vc5_gamma_entry pwl_b[SCALER5_DSPGAMMA_NUM_POINTS]; ++ struct vc5_gamma_entry pwl_a[SCALER5_DSPGAMMA_NUM_POINTS]; ++ }; ++ }; + + struct drm_pending_vblank_event *event; + + struct debugfs_regset32 regset; ++ ++ /** ++ * @feeds_txp: True if the CRTC feeds our writeback controller. ++ */ ++ bool feeds_txp; ++ ++ /** ++ * @irq_lock: Spinlock protecting the resources shared between ++ * the atomic code and our vblank handler. ++ */ ++ spinlock_t irq_lock; ++ ++ /** ++ * @current_dlist: Start offset of the display list currently ++ * set in the HVS for that CRTC. Protected by @irq_lock, and ++ * copied in vc4_hvs_update_dlist() for the CRTC interrupt ++ * handler to have access to that value. ++ */ ++ unsigned int current_dlist; ++ ++ /** ++ * @current_hvs_channel: HVS channel currently assigned to the ++ * CRTC. Protected by @irq_lock, and copied in ++ * vc4_hvs_atomic_begin() for the CRTC interrupt handler to have ++ * access to that value. ++ */ ++ unsigned int current_hvs_channel; + }; + + static inline struct vc4_crtc * +@@ -517,11 +569,16 @@ vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc) return container_of(data, struct vc4_pv_data, base); } ++struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc, ++ struct drm_crtc_state *state); ++ +struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, + struct drm_crtc_state *state); + struct vc4_crtc_state { struct drm_crtc_state base; /* Dlist area for this CRTC configuration. */ -@@ -533,6 +538,8 @@ struct vc4_crtc_state { + struct drm_mm_node mm; +- bool feed_txp; + bool txp_armed; + unsigned int assigned_channel; + +@@ -532,6 +589,8 @@ struct vc4_crtc_state { unsigned int bottom; } margins; @@ -56486,7 +59521,7 @@ index 9809c3a856c6..7c749e08cb0c 100644 /* Transitional state below, only valid during atomic commits */ bool update_muxing; }; -@@ -877,6 +884,9 @@ extern struct platform_driver vc4_dsi_driver; +@@ -876,6 +935,9 @@ extern struct platform_driver vc4_dsi_driver; /* vc4_fence.c */ extern const struct dma_fence_ops vc4_fence_ops; @@ -56496,7 +59531,7 @@ index 9809c3a856c6..7c749e08cb0c 100644 /* vc4_gem.c */ int vc4_gem_init(struct drm_device *dev); int vc4_submit_cl_ioctl(struct drm_device *dev, void *data, -@@ -917,10 +927,10 @@ void vc4_irq_reset(struct drm_device *dev); +@@ -916,10 +978,11 @@ void vc4_irq_reset(struct drm_device *dev); extern struct platform_driver vc4_hvs_driver; void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output); int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output); @@ -56505,6 +59540,7 @@ index 9809c3a856c6..7c749e08cb0c 100644 -void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); -void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state); +int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); ++void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state); +void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); @@ -56512,63 +59548,10 @@ index 9809c3a856c6..7c749e08cb0c 100644 void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel); void vc4_hvs_mask_underrun(struct drm_device *dev, int channel); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -index eaf276978ee7..1c6939c9c232 100644 +index 0bda40c2d787..6e50e1d2eac8 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -181,8 +181,50 @@ - - #define DSI0_TXPKT_PIX_FIFO 0x20 /* AKA PIX_FIFO */ - --#define DSI0_INT_STAT 0x24 --#define DSI0_INT_EN 0x28 -+#define DSI0_INT_STAT 0x24 -+#define DSI0_INT_EN 0x28 -+# define DSI0_INT_FIFO_ERR BIT(25) -+# define DSI0_INT_CMDC_DONE_MASK VC4_MASK(24, 23) -+# define DSI0_INT_CMDC_DONE_SHIFT 23 -+# define DSI0_INT_CMDC_DONE_NO_REPEAT 1 -+# define DSI0_INT_CMDC_DONE_REPEAT 3 -+# define DSI0_INT_PHY_DIR_RTF BIT(22) -+# define DSI0_INT_PHY_D1_ULPS BIT(21) -+# define DSI0_INT_PHY_D1_STOP BIT(20) -+# define DSI0_INT_PHY_RXLPDT BIT(19) -+# define DSI0_INT_PHY_RXTRIG BIT(18) -+# define DSI0_INT_PHY_D0_ULPS BIT(17) -+# define DSI0_INT_PHY_D0_LPDT BIT(16) -+# define DSI0_INT_PHY_D0_FTR BIT(15) -+# define DSI0_INT_PHY_D0_STOP BIT(14) -+/* Signaled when the clock lane enters the given state. */ -+# define DSI0_INT_PHY_CLK_ULPS BIT(13) -+# define DSI0_INT_PHY_CLK_HS BIT(12) -+# define DSI0_INT_PHY_CLK_FTR BIT(11) -+/* Signaled on timeouts */ -+# define DSI0_INT_PR_TO BIT(10) -+# define DSI0_INT_TA_TO BIT(9) -+# define DSI0_INT_LPRX_TO BIT(8) -+# define DSI0_INT_HSTX_TO BIT(7) -+/* Contention on a line when trying to drive the line low */ -+# define DSI0_INT_ERR_CONT_LP1 BIT(6) -+# define DSI0_INT_ERR_CONT_LP0 BIT(5) -+/* Control error: incorrect line state sequence on data lane 0. */ -+# define DSI0_INT_ERR_CONTROL BIT(4) -+# define DSI0_INT_ERR_SYNC_ESC BIT(3) -+# define DSI0_INT_RX2_PKT BIT(2) -+# define DSI0_INT_RX1_PKT BIT(1) -+# define DSI0_INT_CMD_PKT BIT(0) -+ -+#define DSI0_INTERRUPTS_ALWAYS_ENABLED (DSI0_INT_ERR_SYNC_ESC | \ -+ DSI0_INT_ERR_CONTROL | \ -+ DSI0_INT_ERR_CONT_LP0 | \ -+ DSI0_INT_ERR_CONT_LP1 | \ -+ DSI0_INT_HSTX_TO | \ -+ DSI0_INT_LPRX_TO | \ -+ DSI0_INT_TA_TO | \ -+ DSI0_INT_PR_TO) -+ - # define DSI1_INT_PHY_D3_ULPS BIT(30) - # define DSI1_INT_PHY_D3_STOP BIT(29) - # define DSI1_INT_PHY_D2_ULPS BIT(28) -@@ -306,11 +348,11 @@ +@@ -348,11 +348,11 @@ # define DSI0_PHY_AFEC0_RESET BIT(11) # define DSI1_PHY_AFEC0_PD_BG BIT(11) # define DSI0_PHY_AFEC0_PD BIT(10) @@ -56582,187 +59565,16 @@ index eaf276978ee7..1c6939c9c232 100644 # define DSI_PHY_AFEC0_PTATADJ_MASK VC4_MASK(7, 4) # define DSI_PHY_AFEC0_PTATADJ_SHIFT 4 # define DSI_PHY_AFEC0_CTATADJ_MASK VC4_MASK(3, 0) -@@ -493,6 +535,18 @@ - */ - #define DSI1_ID 0x8c - -+struct vc4_dsi_variant { -+ /* Whether we're on bcm2835's DSI0 or DSI1. */ -+ unsigned int port; -+ -+ bool broken_axi_workaround; -+ -+ const char *debugfs_name; -+ const struct debugfs_reg32 *regs; -+ size_t nregs; -+ -+}; -+ - /* General DSI hardware state. */ - struct vc4_dsi { - struct platform_device *pdev; -@@ -509,8 +563,7 @@ struct vc4_dsi { - u32 *reg_dma_mem; - dma_addr_t reg_paddr; - -- /* Whether we're on bcm2835's DSI0 or DSI1. */ -- int port; -+ const struct vc4_dsi_variant *variant; - - /* DSI channel for the panel we're connected to. */ - u32 channel; -@@ -586,10 +639,10 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val) - #define DSI_READ(offset) readl(dsi->regs + (offset)) - #define DSI_WRITE(offset, val) dsi_dma_workaround_write(dsi, offset, val) - #define DSI_PORT_READ(offset) \ -- DSI_READ(dsi->port ? DSI1_##offset : DSI0_##offset) -+ DSI_READ(dsi->variant->port ? DSI1_##offset : DSI0_##offset) - #define DSI_PORT_WRITE(offset, val) \ -- DSI_WRITE(dsi->port ? DSI1_##offset : DSI0_##offset, val) --#define DSI_PORT_BIT(bit) (dsi->port ? DSI1_##bit : DSI0_##bit) -+ DSI_WRITE(dsi->variant->port ? DSI1_##offset : DSI0_##offset, val) -+#define DSI_PORT_BIT(bit) (dsi->variant->port ? DSI1_##bit : DSI0_##bit) - - /* VC4 DSI encoder KMS struct */ - struct vc4_dsi_encoder { -@@ -750,6 +803,9 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) - list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { - if (iter->funcs->disable) - iter->funcs->disable(iter); -+ -+ if (iter == dsi->bridge) -+ break; - } - - vc4_dsi_ulps(dsi, true); -@@ -794,11 +850,9 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, +@@ -850,7 +850,7 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, /* Find what divider gets us a faster clock than the requested * pixel clock. */ -- for (divider = 1; divider < 8; divider++) { -- if (parent_rate / divider < pll_clock) { -- divider--; +- for (divider = 1; divider < 255; divider++) { + for (divider = 1; divider < 7; divider++) { -+ if (parent_rate / (divider + 1) < pll_clock) + if (parent_rate / (divider + 1) < pll_clock) break; -- } - } - - /* Now that we've picked a PLL divider, calculate back to its -@@ -837,7 +891,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - - ret = pm_runtime_get_sync(dev); - if (ret) { -- DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->port); -+ DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port); - return; } - -@@ -871,7 +925,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - DSI_PORT_WRITE(STAT, DSI_PORT_READ(STAT)); - - /* Set AFE CTR00/CTR1 to release powerdown of analog. */ -- if (dsi->port == 0) { -+ if (dsi->variant->port == 0) { - u32 afec0 = (VC4_SET_FIELD(7, DSI_PHY_AFEC0_PTATADJ) | - VC4_SET_FIELD(7, DSI_PHY_AFEC0_CTATADJ)); - -@@ -883,6 +937,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - - DSI_PORT_WRITE(PHY_AFEC0, afec0); - -+ /* AFEC reset hold time */ -+ mdelay(1); -+ - DSI_PORT_WRITE(PHY_AFEC1, - VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE1) | - VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE0) | -@@ -1017,7 +1074,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - DSI_PORT_BIT(PHYC_CLANE_ENABLE) | - ((dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? - 0 : DSI_PORT_BIT(PHYC_HS_CLK_CONTINUOUS)) | -- (dsi->port == 0 ? -+ (dsi->variant->port == 0 ? - VC4_SET_FIELD(lpx - 1, DSI0_PHYC_ESC_CLK_LPDT) : - VC4_SET_FIELD(lpx - 1, DSI1_PHYC_ESC_CLK_LPDT))); - -@@ -1043,18 +1100,15 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - DSI_DISP1_ENABLE); - - /* Ungate the block. */ -- if (dsi->port == 0) -+ if (dsi->variant->port == 0) - DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI0_CTRL_CTRL0); - else - DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI1_CTRL_EN); - - /* Bring AFE out of reset. */ -- if (dsi->port == 0) { -- } else { -- DSI_PORT_WRITE(PHY_AFEC0, -- DSI_PORT_READ(PHY_AFEC0) & -- ~DSI1_PHY_AFEC0_RESET); -- } -+ DSI_PORT_WRITE(PHY_AFEC0, -+ DSI_PORT_READ(PHY_AFEC0) & -+ ~DSI_PORT_BIT(PHY_AFEC0_RESET)); - - vc4_dsi_ulps(dsi, false); - -@@ -1173,13 +1227,28 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, - /* Enable the appropriate interrupt for the transfer completion. */ - dsi->xfer_result = 0; - reinit_completion(&dsi->xfer_completion); -- DSI_PORT_WRITE(INT_STAT, DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); -- if (msg->rx_len) { -- DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -- DSI1_INT_PHY_DIR_RTF)); -+ if (dsi->variant->port == 0) { -+ DSI_PORT_WRITE(INT_STAT, -+ DSI0_INT_CMDC_DONE_MASK | DSI1_INT_PHY_DIR_RTF); -+ if (msg->rx_len) { -+ DSI_PORT_WRITE(INT_EN, (DSI0_INTERRUPTS_ALWAYS_ENABLED | -+ DSI0_INT_PHY_DIR_RTF)); -+ } else { -+ DSI_PORT_WRITE(INT_EN, -+ (DSI0_INTERRUPTS_ALWAYS_ENABLED | -+ VC4_SET_FIELD(DSI0_INT_CMDC_DONE_NO_REPEAT, -+ DSI0_INT_CMDC_DONE))); -+ } - } else { -- DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -- DSI1_INT_TXPKT1_DONE)); -+ DSI_PORT_WRITE(INT_STAT, -+ DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); -+ if (msg->rx_len) { -+ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -+ DSI1_INT_PHY_DIR_RTF)); -+ } else { -+ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -+ DSI1_INT_TXPKT1_DONE)); -+ } - } - - /* Send the packet. */ -@@ -1196,7 +1265,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, - ret = dsi->xfer_result; - } - -- DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED)); - - if (ret) - goto reset_fifo_and_return; -@@ -1242,7 +1311,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, - DSI_PORT_BIT(CTRL_RESET_FIFOS)); - - DSI_PORT_WRITE(TXPKT1C, 0); -- DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED)); - return ret; - } - -@@ -1305,8 +1374,32 @@ static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = { +@@ -1374,6 +1374,20 @@ static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = { .mode_fixup = vc4_dsi_encoder_mode_fixup, }; @@ -56780,156 +59592,19 @@ index eaf276978ee7..1c6939c9c232 100644 + .nregs = ARRAY_SIZE(dsi0_regs), +}; + -+static const struct vc4_dsi_variant bcm2835_dsi1_variant = { -+ .port = 1, -+ .broken_axi_workaround = true, -+ .debugfs_name = "dsi1_regs", -+ .regs = dsi1_regs, -+ .nregs = ARRAY_SIZE(dsi1_regs), -+}; -+ + static const struct vc4_dsi_variant bcm2835_dsi1_variant = { + .port = 1, + .broken_axi_workaround = true, +@@ -1383,6 +1397,8 @@ static const struct vc4_dsi_variant bcm2835_dsi1_variant = { + }; + static const struct of_device_id vc4_dsi_dt_match[] = { -- { .compatible = "brcm,bcm2835-dsi1", (void *)(uintptr_t)1 }, + { .compatible = "brcm,bcm2711-dsi1", &bcm2711_dsi1_variant }, + { .compatible = "brcm,bcm2835-dsi0", &bcm2835_dsi0_variant }, -+ { .compatible = "brcm,bcm2835-dsi1", &bcm2835_dsi1_variant }, + { .compatible = "brcm,bcm2835-dsi1", &bcm2835_dsi1_variant }, {} }; - -@@ -1317,7 +1410,7 @@ static void dsi_handle_error(struct vc4_dsi *dsi, - if (!(stat & bit)) - return; - -- DRM_ERROR("DSI%d: %s error\n", dsi->port, type); -+ DRM_ERROR("DSI%d: %s error\n", dsi->variant->port, type); - *ret = IRQ_HANDLED; - } - -@@ -1351,26 +1444,28 @@ static irqreturn_t vc4_dsi_irq_handler(int irq, void *data) - DSI_PORT_WRITE(INT_STAT, stat); - - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_SYNC_ESC, "LPDT sync"); -+ DSI_PORT_BIT(INT_ERR_SYNC_ESC), "LPDT sync"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_CONTROL, "data lane 0 sequence"); -+ DSI_PORT_BIT(INT_ERR_CONTROL), "data lane 0 sequence"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_CONT_LP0, "LP0 contention"); -+ DSI_PORT_BIT(INT_ERR_CONT_LP0), "LP0 contention"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_CONT_LP1, "LP1 contention"); -+ DSI_PORT_BIT(INT_ERR_CONT_LP1), "LP1 contention"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_HSTX_TO, "HSTX timeout"); -+ DSI_PORT_BIT(INT_HSTX_TO), "HSTX timeout"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_LPRX_TO, "LPRX timeout"); -+ DSI_PORT_BIT(INT_LPRX_TO), "LPRX timeout"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_TA_TO, "turnaround timeout"); -+ DSI_PORT_BIT(INT_TA_TO), "turnaround timeout"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_PR_TO, "peripheral reset timeout"); -+ DSI_PORT_BIT(INT_PR_TO), "peripheral reset timeout"); - -- if (stat & (DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF)) { -+ if (stat & ((dsi->variant->port ? DSI1_INT_TXPKT1_DONE : -+ DSI0_INT_CMDC_DONE_MASK) | -+ DSI_PORT_BIT(INT_PHY_DIR_RTF))) { - complete(&dsi->xfer_completion); - ret = IRQ_HANDLED; -- } else if (stat & DSI1_INT_HSTX_TO) { -+ } else if (stat & DSI_PORT_BIT(INT_HSTX_TO)) { - complete(&dsi->xfer_completion); - dsi->xfer_result = -ETIMEDOUT; - ret = IRQ_HANDLED; -@@ -1390,12 +1485,12 @@ vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi) - struct device *dev = &dsi->pdev->dev; - const char *parent_name = __clk_get_name(dsi->pll_phy_clock); - static const struct { -- const char *dsi0_name, *dsi1_name; -+ const char *name; - int div; - } phy_clocks[] = { -- { "dsi0_byte", "dsi1_byte", 8 }, -- { "dsi0_ddr2", "dsi1_ddr2", 4 }, -- { "dsi0_ddr", "dsi1_ddr", 2 }, -+ { "byte", 8 }, -+ { "ddr2", 4 }, -+ { "ddr", 2 }, - }; - int i; - -@@ -1411,8 +1506,12 @@ vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi) - for (i = 0; i < ARRAY_SIZE(phy_clocks); i++) { - struct clk_fixed_factor *fix = &dsi->phy_clocks[i]; - struct clk_init_data init; -+ char clk_name[16]; - int ret; - -+ snprintf(clk_name, sizeof(clk_name), -+ "dsi%u_%s", dsi->variant->port, phy_clocks[i].name); -+ - /* We just use core fixed factor clock ops for the PHY - * clocks. The clocks are actually gated by the - * PHY_AFEC0_DDRCLK_EN bits, which we should be -@@ -1429,10 +1528,7 @@ vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi) - memset(&init, 0, sizeof(init)); - init.parent_names = &parent_name; - init.num_parents = 1; -- if (dsi->port == 1) -- init.name = phy_clocks[i].dsi1_name; -- else -- init.name = phy_clocks[i].dsi0_name; -+ init.name = clk_name; - init.ops = &clk_fixed_factor_ops; - - ret = devm_clk_hw_register(dev, &fix->hw); -@@ -1451,7 +1547,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - { - struct platform_device *pdev = to_platform_device(dev); - struct drm_device *drm = dev_get_drvdata(master); -- struct vc4_dev *vc4 = to_vc4_dev(drm); - struct vc4_dsi *dsi = dev_get_drvdata(dev); - struct vc4_dsi_encoder *vc4_dsi_encoder; - struct drm_panel *panel; -@@ -1463,7 +1558,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - if (!match) - return -ENODEV; - -- dsi->port = (uintptr_t)match->data; -+ dsi->variant = match->data; - - vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder), - GFP_KERNEL); -@@ -1471,7 +1566,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - return -ENOMEM; - - INIT_LIST_HEAD(&dsi->bridge_chain); -- vc4_dsi_encoder->base.type = VC4_ENCODER_TYPE_DSI1; -+ vc4_dsi_encoder->base.type = dsi->variant->port ? -+ VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0; - vc4_dsi_encoder->dsi = dsi; - dsi->encoder = &vc4_dsi_encoder->base.base; - -@@ -1480,13 +1576,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - return PTR_ERR(dsi->regs); - - dsi->regset.base = dsi->regs; -- if (dsi->port == 0) { -- dsi->regset.regs = dsi0_regs; -- dsi->regset.nregs = ARRAY_SIZE(dsi0_regs); -- } else { -- dsi->regset.regs = dsi1_regs; -- dsi->regset.nregs = ARRAY_SIZE(dsi1_regs); -- } -+ dsi->regset.regs = dsi->variant->regs; -+ dsi->regset.nregs = dsi->variant->nregs; - - if (DSI_PORT_READ(ID) != DSI_ID_VALUE) { - dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n", -@@ -1494,11 +1585,11 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1569,8 +1585,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) return -ENODEV; } @@ -56939,12 +59614,8 @@ index eaf276978ee7..1c6939c9c232 100644 + * writes from the ARM. It does handle writes from the DMA engine, * so set up a channel for talking to it. */ -- if (dsi->port == 1) { -+ if (dsi->variant->broken_axi_workaround) { - dsi->reg_dma_mem = dma_alloc_coherent(dev, 4, - &dsi->reg_dma_paddr, - GFP_KERNEL); -@@ -1515,7 +1606,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) + if (dsi->variant->broken_axi_workaround) { +@@ -1590,7 +1606,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) if (ret != -EPROBE_DEFER) DRM_ERROR("Failed to get DMA channel: %d\n", ret); @@ -56953,7 +59624,7 @@ index eaf276978ee7..1c6939c9c232 100644 } /* Get the physical address of the device's registers. The -@@ -1544,7 +1635,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1619,7 +1635,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) if (ret) { if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get interrupt: %d\n", ret); @@ -56962,7 +59633,7 @@ index eaf276978ee7..1c6939c9c232 100644 } dsi->escape_clock = devm_clk_get(dev, "escape"); -@@ -1552,7 +1643,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1627,7 +1643,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) ret = PTR_ERR(dsi->escape_clock); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get escape clock: %d\n", ret); @@ -56971,7 +59642,7 @@ index eaf276978ee7..1c6939c9c232 100644 } dsi->pll_phy_clock = devm_clk_get(dev, "phy"); -@@ -1560,7 +1651,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1635,7 +1651,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) ret = PTR_ERR(dsi->pll_phy_clock); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get phy clock: %d\n", ret); @@ -56980,7 +59651,7 @@ index eaf276978ee7..1c6939c9c232 100644 } dsi->pixel_clock = devm_clk_get(dev, "pixel"); -@@ -1568,7 +1659,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1643,7 +1659,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) ret = PTR_ERR(dsi->pixel_clock); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get pixel clock: %d\n", ret); @@ -56989,7 +59660,7 @@ index eaf276978ee7..1c6939c9c232 100644 } ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, -@@ -1583,29 +1674,28 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1658,26 +1674,28 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) if (ret == -ENODEV) return 0; @@ -57019,14 +59690,11 @@ index eaf276978ee7..1c6939c9c232 100644 ret = vc4_dsi_init_phy_clocks(dsi); if (ret) - return ret; -- -- if (dsi->port == 1) -- vc4->dsi1 = dsi; + goto err_free_dma; drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI); drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); -@@ -1613,7 +1703,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) +@@ -1685,7 +1703,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0); if (ret) { dev_err(dev, "bridge attach failed: %d\n", ret); @@ -57035,16 +59703,7 @@ index eaf276978ee7..1c6939c9c232 100644 } /* Disable the atomic helper calls into the bridge. We * manually call the bridge pre_enable / enable / etc. calls -@@ -1622,21 +1712,29 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - */ - list_splice_init(&dsi->encoder->bridge_chain, &dsi->bridge_chain); - -- if (dsi->port == 0) -- vc4_debugfs_add_regset32(drm, "dsi0_regs", &dsi->regset); -- else -- vc4_debugfs_add_regset32(drm, "dsi1_regs", &dsi->regset); -+ vc4_debugfs_add_regset32(drm, dsi->variant->debugfs_name, &dsi->regset); - +@@ -1699,6 +1717,19 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(dev); return 0; @@ -57064,19 +59723,11 @@ index eaf276978ee7..1c6939c9c232 100644 } static void vc4_dsi_unbind(struct device *dev, struct device *master, - void *data) - { -- struct drm_device *drm = dev_get_drvdata(master); -- struct vc4_dev *vc4 = to_vc4_dev(drm); - struct vc4_dsi *dsi = dev_get_drvdata(dev); - - if (dsi->bridge) -@@ -1649,8 +1747,15 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, +@@ -1715,6 +1746,16 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, + */ list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain); drm_encoder_cleanup(dsi->encoder); - -- if (dsi->port == 1) -- vc4->dsi1 = NULL; ++ + if (dsi->reg_dma_chan) { + dma_release_channel(dsi->reg_dma_chan); + dsi->reg_dma_chan = NULL; @@ -59109,10 +61760,10 @@ index b641252939d8..445d3bab89e0 100644 /* Scheduled when any job has been completed, this walks the list of diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index ee293f061f0a..f1adaa9dc5f3 100644 +index 08175c3dd374..b34667b9577e 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -35,6 +35,7 @@ +@@ -35,25 +35,39 @@ #include #include #include @@ -59120,7 +61771,11 @@ index ee293f061f0a..f1adaa9dc5f3 100644 #include #include #include -@@ -44,10 +45,13 @@ ++#include ++#include + #include + #include + #include #include #include #include @@ -59134,7 +61789,21 @@ index ee293f061f0a..f1adaa9dc5f3 100644 #include "media/cec.h" #include "vc4_drv.h" #include "vc4_hdmi.h" -@@ -76,11 +80,33 @@ + #include "vc4_hdmi_regs.h" + #include "vc4_regs.h" + ++/* ++ * "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 ++ + #define VC5_HDMI_HORZA_HFP_SHIFT 16 + #define VC5_HDMI_HORZA_HFP_MASK VC4_MASK(28, 16) + #define VC5_HDMI_HORZA_VPOS BIT(15) +@@ -76,15 +90,74 @@ #define VC5_HDMI_VERTB_VSPO_SHIFT 16 #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) @@ -59157,19 +61826,61 @@ index ee293f061f0a..f1adaa9dc5f3 100644 # define VC4_HD_M_SW_RST BIT(2) # define VC4_HD_M_ENABLE BIT(0) -+#define HSM_MIN_CLOCK_FREQ 120000000 + #define HSM_MIN_CLOCK_FREQ 120000000 #define CEC_CLOCK_FREQ 40000 -#define VC4_HSM_MID_CLOCK 149985000 -+#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) +- + #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) + ++/* bit field to force hotplug detection. bit0 = HDMI0 */ ++static int force_hotplug = 0; ++module_param(force_hotplug, int, 0644); + -+static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode) ++static const char * const output_format_str[] = { ++ [VC4_HDMI_OUTPUT_RGB] = "RGB", ++ [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0", ++ [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2", ++ [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4", ++}; ++ ++static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt) +{ -+ return (mode->clock * 1000) > HDMI_14_MAX_TMDS_CLK; ++ if (fmt >= ARRAY_SIZE(output_format_str)) ++ return "invalid"; ++ ++ return output_format_str[fmt]; +} - ++ ++static unsigned long long ++vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, ++ unsigned int bpc, enum vc4_hdmi_output_format fmt); ++ ++static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, ++ unsigned int bpc, ++ enum vc4_hdmi_output_format fmt) ++{ ++ unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); ++ ++ return clock > HDMI_14_MAX_TMDS_CLK; ++} ++ ++static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi, ++ const struct drm_display_mode *mode) ++{ ++ struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; ++ ++ if (vc4_hdmi->broadcast_rgb == VC4_BROADCAST_RGB_LIMITED) ++ return false; ++ else if (vc4_hdmi->broadcast_rgb == VC4_BROADCAST_RGB_FULL) ++ return true; ++ return !vc4_encoder->hdmi_monitor || ++ drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL; ++} ++ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { -@@ -90,6 +116,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) + struct drm_info_node *node = (struct drm_info_node *)m->private; +@@ -93,12 +166,22 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); drm_print_regset32(&p, &vc4_hdmi->hd_regset); @@ -59182,16 +61893,65 @@ index ee293f061f0a..f1adaa9dc5f3 100644 return 0; } -@@ -132,7 +164,7 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) + + static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HDMI_WRITE(HDMI_M_CTL, 0); +@@ -110,24 +193,36 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) + VC4_HDMI_SW_RESET_FORMAT_DETECT); + + HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ + reset_control_reset(vc4_hdmi->reset); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + HDMI_WRITE(HDMI_DVP_CTL, 0); + + HDMI_WRITE(HDMI_CLOCK_STOP, + HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + #ifdef CONFIG_DRM_VC4_HDMI_CEC + static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long cec_rate = clk_get_rate(vc4_hdmi->cec_clock); ++ unsigned long flags; + u16 clk_cnt; + u32 value; + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + value = HDMI_READ(HDMI_CEC_CNTRL_1); + value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; + +@@ -135,30 +230,39 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) * Set the clock divider: the hsm_clock rate and this divider * setting will give a 40 kHz CEC clock. */ - clk_cnt = clk_get_rate(vc4_hdmi->hsm_clock) / CEC_CLOCK_FREQ; -+ clk_cnt = clk_get_rate(vc4_hdmi->cec_clock) / CEC_CLOCK_FREQ; ++ clk_cnt = cec_rate / CEC_CLOCK_FREQ; value |= clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT; HDMI_WRITE(HDMI_CEC_CNTRL_1, value); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); } -@@ -140,10 +172,13 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) + #else static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} #endif @@ -59204,17 +61964,34 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + enum drm_connector_status ret = connector_status_disconnected; bool connected = false; ++ mutex_lock(&vc4_hdmi->mutex); ++ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); -@@ -152,8 +187,6 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + +- if (vc4_hdmi->hpd_gpio) { ++ if (force_hotplug & BIT(vc4_hdmi->encoder.base.type - VC4_ENCODER_TYPE_HDMI0)) ++ connected = true; ++ else if (vc4_hdmi->hpd_gpio) { if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ vc4_hdmi->hpd_active_low) connected = true; - } else if (drm_probe_ddc(vc4_hdmi->ddc)) { - connected = true; - } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) { - connected = true; +- } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) { +- connected = true; ++ } else { ++ if (vc4_hdmi->variant->hp_detect && ++ vc4_hdmi->variant->hp_detect(vc4_hdmi)) ++ connected = true; } -@@ -169,13 +202,17 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + + if (connected) { +@@ -169,16 +273,25 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); + vc4_hdmi->encoder.hdmi_monitor = drm_detect_hdmi_monitor(edid); + kfree(edid); ++ } else { ++ vc4_hdmi->encoder.hdmi_monitor = false; } } @@ -59226,16 +62003,36 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + goto out; } ++ vc4_hdmi->encoder.hdmi_monitor = false; ++ cec_phys_addr_invalidate(vc4_hdmi->cec_adap); + +out: pm_runtime_put(&vc4_hdmi->pdev->dev); - return connector_status_disconnected; ++ mutex_unlock(&vc4_hdmi->mutex); + return ret; } static void vc4_hdmi_connector_destroy(struct drm_connector *connector) -@@ -202,26 +239,97 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) +@@ -194,10 +307,14 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) + int ret = 0; + struct edid *edid; + ++ mutex_lock(&vc4_hdmi->mutex); ++ + edid = drm_get_edid(connector, vc4_hdmi->ddc); + cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); +- if (!edid) +- return -ENODEV; ++ if (!edid) { ++ ret = -ENODEV; ++ goto out; ++ } + + vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); + +@@ -205,15 +322,152 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) ret = drm_add_edid_modes(connector, edid); kfree(edid); @@ -59244,12 +62041,15 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + struct drm_display_mode *mode; + + list_for_each_entry(mode, &connector->probed_modes, head) { -+ if (vc4_hdmi_mode_needs_scrambling(mode)) { ++ if (vc4_hdmi_mode_needs_scrambling(mode, 8, VC4_HDMI_OUTPUT_RGB)) { + drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); + drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); + } + } + } ++ ++out: ++ mutex_unlock(&vc4_hdmi->mutex); + return ret; } @@ -59259,14 +62059,17 @@ index ee293f061f0a..f1adaa9dc5f3 100644 +{ + struct drm_connector_state *old_state = + drm_atomic_get_old_connector_state(state, connector); ++ struct vc4_hdmi_connector_state *old_vc4_state = conn_state_to_vc4_hdmi_conn_state(old_state); + struct drm_connector_state *new_state = + drm_atomic_get_new_connector_state(state, connector); ++ struct vc4_hdmi_connector_state *new_vc4_state = conn_state_to_vc4_hdmi_conn_state(new_state); + struct drm_crtc *crtc = new_state->crtc; + + if (!crtc) + return 0; + + if (old_state->colorspace != new_state->colorspace || ++ old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb || + !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) { + struct drm_crtc_state *crtc_state; + @@ -59279,6 +62082,65 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + + return 0; +} ++ ++/** ++ * vc4_hdmi_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_hdmi_connector_get_property(struct drm_connector *connector, ++ const struct drm_connector_state *state, ++ struct drm_property *property, ++ uint64_t *val) ++{ ++ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); ++ const struct vc4_hdmi_connector_state *vc4_conn_state = ++ const_conn_state_to_vc4_hdmi_conn_state(state); ++ ++ if (property == vc4_hdmi->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_hdmi_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_hdmi_connector_set_property(struct drm_connector *connector, ++ struct drm_connector_state *state, ++ struct drm_property *property, ++ uint64_t val) ++{ ++ struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); ++ struct vc4_hdmi_connector_state *vc4_conn_state = ++ conn_state_to_vc4_hdmi_conn_state(state); ++ ++ if (property == vc4_hdmi->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 void vc4_hdmi_connector_reset(struct drm_connector *connector) { @@ -59287,8 +62149,9 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + conn_state_to_vc4_hdmi_conn_state(connector->state); + struct vc4_hdmi_connector_state *new_state = + kzalloc(sizeof(*new_state), GFP_KERNEL); -+ -+ if (connector->state) + + if (connector->state) +- drm_atomic_helper_connector_tv_reset(connector); + __drm_atomic_helper_connector_destroy_state(connector->state); + + kfree(old_state); @@ -59299,9 +62162,10 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + + new_state->base.max_bpc = 8; + new_state->base.max_requested_bpc = 8; - drm_atomic_helper_connector_tv_reset(connector); - } - ++ new_state->output_format = VC4_HDMI_OUTPUT_RGB; ++ drm_atomic_helper_connector_tv_reset(connector); ++} ++ +static struct drm_connector_state * +vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) +{ @@ -59314,28 +62178,61 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + return NULL; + + new_state->pixel_rate = vc4_state->pixel_rate; ++ new_state->output_bpc = vc4_state->output_bpc; ++ new_state->output_format = vc4_state->output_format; ++ new_state->broadcast_rgb = vc4_state->broadcast_rgb; + __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); + + return &new_state->base; -+} -+ + } + static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { - .detect = vc4_hdmi_connector_detect, +@@ -221,14 +475,43 @@ static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .destroy = vc4_hdmi_connector_destroy, .reset = vc4_hdmi_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++ .atomic_get_property = vc4_hdmi_connector_get_property, ++ .atomic_set_property = vc4_hdmi_connector_set_property, }; static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = { .get_modes = vc4_hdmi_connector_get_modes, + .atomic_check = vc4_hdmi_connector_atomic_check, ++}; ++ ++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_hdmi_attach_broadcast_rgb_property(struct drm_device *dev, ++ struct vc4_hdmi *vc4_hdmi) ++{ ++ struct drm_property *prop = vc4_hdmi->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; ++ ++ vc4_hdmi->broadcast_rgb_property = prop; ++ } ++ ++ drm_object_attach_property(&vc4_hdmi->connector.base, prop, 0); ++} ++ static int vc4_hdmi_connector_init(struct drm_device *dev, -@@ -237,18 +345,35 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, + struct vc4_hdmi *vc4_hdmi) + { +@@ -242,18 +525,37 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, vc4_hdmi->ddc); drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); @@ -59368,10 +62265,12 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + + if (vc4_hdmi->variant->supports_hdr) + drm_connector_attach_hdr_output_metadata_property(connector); ++ ++ vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi); drm_connector_attach_encoder(connector, encoder); -@@ -256,7 +381,8 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, +@@ -261,13 +563,20 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, } static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, @@ -59381,17 +62280,19 @@ index ee293f061f0a..f1adaa9dc5f3 100644 { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); u32 packet_id = type - 0x80; -@@ -264,6 +390,9 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, ++ unsigned long flags; + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); - ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + if (!poll) + return 0; -+ + return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) & BIT(packet_id)), 100); - } -@@ -276,9 +405,11 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, +@@ -281,9 +590,12 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, const struct vc4_hdmi_register *ram_packet_start = &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; @@ -59401,10 +62302,11 @@ index ee293f061f0a..f1adaa9dc5f3 100644 ram_packet_start->reg); - uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; + uint8_t buffer[VC4_HDMI_PACKET_STRIDE] = {}; ++ unsigned long flags; ssize_t len, i; int ret; -@@ -290,7 +421,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, +@@ -295,12 +607,14 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, if (len < 0) return; @@ -59413,7 +62315,14 @@ index ee293f061f0a..f1adaa9dc5f3 100644 if (ret) { DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); return; -@@ -311,6 +442,13 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, + } + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + for (i = 0; i < len; i += 7) { + writel(buffer[i + 0] << 0 | + buffer[i + 1] << 8 | +@@ -316,25 +630,62 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, packet_reg += 4; } @@ -59426,17 +62335,76 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) & -@@ -342,7 +480,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) - vc4_encoder->limited_rgb_range ? - HDMI_QUANTIZATION_RANGE_LIMITED : - HDMI_QUANTIZATION_RANGE_FULL); + BIT(packet_id)), 100); + if (ret) + DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); + } + ++static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, ++ enum vc4_hdmi_output_format fmt) ++{ ++ switch (fmt) { ++ case VC4_HDMI_OUTPUT_RGB: ++ frame->colorspace = HDMI_COLORSPACE_RGB; ++ break; ++ ++ case VC4_HDMI_OUTPUT_YUV420: ++ frame->colorspace = HDMI_COLORSPACE_YUV420; ++ break; ++ ++ case VC4_HDMI_OUTPUT_YUV422: ++ frame->colorspace = HDMI_COLORSPACE_YUV422; ++ break; ++ ++ case VC4_HDMI_OUTPUT_YUV444: ++ frame->colorspace = HDMI_COLORSPACE_YUV444; ++ break; ++ ++ default: ++ break; ++ } ++} ++ + static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) + { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); +- struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector_state *cstate = connector->state; +- struct drm_crtc *crtc = encoder->crtc; +- const struct drm_display_mode *mode = &crtc->state->adjusted_mode; ++ struct vc4_hdmi_connector_state *vc4_state = ++ conn_state_to_vc4_hdmi_conn_state(cstate); ++ const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + union hdmi_infoframe frame; + int ret; + ++ lockdep_assert_held(&vc4_hdmi->mutex); ++ + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, + connector, mode); + if (ret < 0) { +@@ -344,10 +695,11 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) + + drm_hdmi_avi_infoframe_quant_range(&frame.avi, + connector, mode, +- vc4_encoder->limited_rgb_range ? +- HDMI_QUANTIZATION_RANGE_LIMITED : +- HDMI_QUANTIZATION_RANGE_FULL); - -+ drm_hdmi_avi_infoframe_colorspace(&frame.avi, cstate); ++ vc4_hdmi_is_full_range(vc4_hdmi, mode) ? ++ HDMI_QUANTIZATION_RANGE_FULL : ++ HDMI_QUANTIZATION_RANGE_LIMITED); ++ drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate); ++ vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); drm_hdmi_avi_infoframe_bars(&frame.avi, cstate); vc4_hdmi_write_infoframe(encoder, &frame); -@@ -367,15 +505,28 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) +@@ -372,15 +724,30 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); @@ -59448,11 +62416,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + memcpy(&frame.audio, audio, sizeof(*audio)); + vc4_hdmi_write_infoframe(encoder, &frame); +} - -- frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; -- frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; -- frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; -- frame.audio.channels = vc4_hdmi->audio.channels; ++ +static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); @@ -59460,18 +62424,33 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + struct drm_connector_state *conn_state = connector->state; + union hdmi_infoframe frame; + ++ lockdep_assert_held(&vc4_hdmi->mutex); ++ + if (!vc4_hdmi->variant->supports_hdr) + return; + + if (!conn_state->hdr_output_metadata) + return; -+ + +- frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; +- frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; +- frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; +- frame.audio.channels = vc4_hdmi->audio.channels; + if (drm_hdmi_infoframe_set_hdr_metadata(&frame.drm, conn_state)) + return; vc4_hdmi_write_infoframe(encoder, &frame); } -@@ -392,33 +543,128 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) +@@ -389,6 +756,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) + { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + ++ lockdep_assert_held(&vc4_hdmi->mutex); ++ + vc4_hdmi_set_avi_infoframe(encoder); + vc4_hdmi_set_spd_infoframe(encoder); + /* +@@ -397,52 +766,176 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) */ if (vc4_hdmi->audio.streaming) vc4_hdmi_set_audio_infoframe(encoder); @@ -59486,6 +62465,8 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_display_info *display = &vc4_hdmi->connector.display_info; + ++ lockdep_assert_held(&vc4_hdmi->mutex); ++ + if (!vc4_encoder->hdmi_monitor) + return false; + @@ -59494,31 +62475,38 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + return false; + + return true; - } - --static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) ++} ++ +#define SCRAMBLING_POLLING_DELAY_MS 1000 + +static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) +{ -+ struct drm_display_mode *mode; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; ++ unsigned long flags; ++ ++ lockdep_assert_held(&vc4_hdmi->mutex); + + if (!encoder->crtc || !encoder->crtc->state) + return; + -+ mode = &encoder->crtc->state->adjusted_mode; + if (!vc4_hdmi_supports_scrambling(encoder, mode)) + return; + -+ if (!vc4_hdmi_mode_needs_scrambling(mode)) ++ if (!vc4_hdmi_mode_needs_scrambling(mode, ++ vc4_hdmi->output_bpc, ++ vc4_hdmi->output_format)) + return; + + drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); + drm_scdc_set_scrambling(vc4_hdmi->ddc, true); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) | + VC5_HDMI_SCRAMBLER_CTL_ENABLE); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ ++ vc4_hdmi->scdc_enabled = true; + + queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, + msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); @@ -59527,24 +62515,22 @@ index ee293f061f0a..f1adaa9dc5f3 100644 +static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ struct drm_crtc *crtc = encoder->crtc; ++ unsigned long flags; + -+ /* -+ * At boot, encoder->crtc will be NULL. Since we don't know the -+ * state of the scrambler and in order to avoid any -+ * inconsistency, let's disable it all the time. -+ */ -+ if (crtc && !vc4_hdmi_supports_scrambling(encoder, &crtc->mode)) -+ return; ++ lockdep_assert_held(&vc4_hdmi->mutex); + -+ if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode)) ++ if (!vc4_hdmi->scdc_enabled) + return; + ++ vc4_hdmi->scdc_enabled = false; ++ + if (delayed_work_pending(&vc4_hdmi->scrambling_work)) + cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) & + ~VC5_HDMI_SCRAMBLER_CTL_ENABLE); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + drm_scdc_set_scrambling(vc4_hdmi->ddc, false); + drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); @@ -59564,12 +62550,19 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + + queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, + msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); -+} -+ + } + +-static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ unsigned long flags; ++ ++ mutex_lock(&vc4_hdmi->mutex); ++ ++ vc4_hdmi->output_enabled = false; ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); @@ -59577,12 +62570,19 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC); + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB); + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + mdelay(1); ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); + HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + vc4_hdmi_disable_scrambling(encoder); ++ ++ mutex_unlock(&vc4_hdmi->mutex); } -static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) @@ -59590,17 +62590,22 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + struct drm_atomic_state *state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ unsigned long flags; int ret; -+ HDMI_WRITE(HDMI_VID_CTL, +- if (vc4_hdmi->variant->phy_disable) +- vc4_hdmi->variant->phy_disable(vc4_hdmi); ++ mutex_lock(&vc4_hdmi->mutex); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_VID_CTL, +- HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); + HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + - if (vc4_hdmi->variant->phy_disable) - vc4_hdmi->variant->phy_disable(vc4_hdmi); ++ if (vc4_hdmi->variant->phy_disable) ++ vc4_hdmi->variant->phy_disable(vc4_hdmi); -- HDMI_WRITE(HDMI_VID_CTL, -- HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); -- clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); + if (vc4_hdmi->bvb_req) + clk_request_done(vc4_hdmi->bvb_req); @@ -59608,65 +62613,374 @@ index ee293f061f0a..f1adaa9dc5f3 100644 clk_disable_unprepare(vc4_hdmi->pixel_clock); ret = pm_runtime_put(&vc4_hdmi->pdev->dev); -@@ -505,6 +751,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) + if (ret < 0) + DRM_ERROR("Failed to release power domain: %d\n", ret); +-} + +-static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +-{ ++ mutex_unlock(&vc4_hdmi->mutex); } - static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, -+ struct drm_connector_state *state, - struct drm_display_mode *mode) +-static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) ++static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, ++ struct drm_connector_state *state, ++ const struct drm_display_mode *mode) { ++ unsigned long flags; + u32 csc_ctl; + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, + VC4_HD_CSC_CTL_ORDER); + +- if (enable) { ++ if (!vc4_hdmi_is_full_range(vc4_hdmi, mode)) { + /* CEA VICs other than #1 requre limited range RGB + * output unless overridden by an AVI infoframe. + * Apply a colorspace conversion to squash 0-255 down +@@ -468,50 +961,242 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) + + /* The RGB order applies even when CSC is disabled. */ + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); +-} +- +-static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) +-{ +- u32 csc_ctl; + +- csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++} + +- if (enable) { +- /* CEA VICs other than #1 requre limited range RGB +- * output unless overridden by an AVI infoframe. +- * Apply a colorspace conversion to squash 0-255 down +- * to 16-235. The matrix here is: +- * +- * [ 0.8594 0 0 16] +- * [ 0 0.8594 0 16] +- * [ 0 0 0.8594 16] +- * [ 0 0 0 1] +- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets +- */ +- HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80); +- HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80); +- } else { +- /* Still use the matrix for full range, but make it unity. +- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets +- */ +- HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000); +- HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000); ++/* ++ * If we need to output Full Range RGB, then use the unity matrix ++ * ++ * [ 1 0 0 0] ++ * [ 0 1 0 0] ++ * [ 0 0 1 0] ++ * ++ * CEA VICs other than #1 require limited range RGB output unless ++ * overridden by an AVI infoframe. Apply a colorspace conversion to ++ * squash 0-255 down to 16-235. The matrix here is: ++ * ++ * [ 0.8594 0 0 16] ++ * [ 0 0.8594 0 16] ++ * [ 0 0 0.8594 16] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_to_rgb[2][3][4] = { ++ { ++ /* Full range - unity */ ++ { 0x2000, 0x0000, 0x0000, 0x0000 }, ++ { 0x0000, 0x2000, 0x0000, 0x0000 }, ++ { 0x0000, 0x0000, 0x2000, 0x0000 }, ++ }, { ++ /* Limited range */ ++ { 0x1b80, 0x0000, 0x0000, 0x0400 }, ++ { 0x0000, 0x1b80, 0x0000, 0x0400 }, ++ { 0x0000, 0x0000, 0x1b80, 0x0400 }, + } ++}; + +- HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); +-} ++/* ++ * Conversion between Full Range RGB and YUV using the BT.601 Colorspace ++ * ++ * Full range ++ * [ 0.299000 0.587000 0.114000 0.000000 ] ++ * [ -0.168736 -0.331264 0.500000 128.000000 ] ++ * [ 0.500000 -0.418688 -0.081312 128.000000 ] ++ * ++ * Limited range ++ * [ 0.255785 0.502160 0.097523 16.000000 ] ++ * [ -0.147644 -0.289856 0.437500 128.000000 ] ++ * [ 0.437500 -0.366352 -0.071148 128.000000 ] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt601[2][3][4] = { ++ { ++ /* Full range */ ++ { 0x0991, 0x12c9, 0x03a6, 0x0000 }, ++ { 0xfa9b, 0xf567, 0x1000, 0x2000 }, ++ { 0x1000, 0xf29b, 0xfd67, 0x2000 }, ++ }, { ++ /* Limited range */ ++ { 0x082f, 0x1012, 0x031f, 0x0400 }, ++ { 0xfb48, 0xf6ba, 0x0e00, 0x2000 }, ++ { 0x0e00, 0xf448, 0xfdba, 0x2000 }, ++ } ++}; + +-static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, +- struct drm_display_mode *mode) +-{ ++/* ++ * Conversion between Full Range RGB and YUV using the BT.709 Colorspace ++ * ++ * Full range ++ * [ 0.212600 0.715200 0.072200 0.000000 ] ++ * [ -0.114572 -0.385428 0.500000 128.000000 ] ++ * [ 0.500000 -0.454153 -0.045847 128.000000 ] ++ * ++ * Limited range ++ * [ 0.181873 0.611831 0.061765 16.000000 ] ++ * [ -0.100251 -0.337249 0.437500 128.000000 ] ++ * [ 0.437500 -0.397384 -0.040116 128.000000 ] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt709[2][3][4] = { ++ { ++ /* Full range */ ++ { 0x06ce, 0x16e3, 0x024f, 0x0000 }, ++ { 0xfc56, 0xf3ac, 0x1000, 0x2000 }, ++ { 0x1000, 0xf179, 0xfe89, 0x2000 }, ++ }, { ++ /* Limited range */ ++ { 0x05d2, 0x1394, 0x01fa, 0x0400 }, ++ { 0xfccc, 0xf536, 0x0e00, 0x2000 }, ++ { 0x0e00, 0xf34a, 0xfeb8, 0x2000 }, ++ } ++}; ++ ++/* ++ * Conversion between Full Range RGB and YUV using the BT.2020 Colorspace ++ * ++ * Full range ++ * [ 0.262700 0.678000 0.059300 0.000000 ] ++ * [ -0.139630 -0.360370 0.500000 128.000000 ] ++ * [ 0.500000 -0.459786 -0.040214 128.000000 ] ++ * ++ * Limited range ++ * [ 0.224732 0.580008 0.050729 16.000000 ] ++ * [ -0.122176 -0.315324 0.437500 128.000000 ] ++ * [ 0.437500 -0.402312 -0.035188 128.000000 ] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt2020[2][3][4] = { ++ { ++ /* Full range */ ++ { 0x0868, 0x15b2, 0x01e6, 0x0000 }, ++ { 0xfb89, 0xf479, 0x1000, 0x2000 }, ++ { 0x1000, 0xf14a, 0xfeb8, 0x2000 }, ++ }, { ++ /* Limited range */ ++ { 0x0731, 0x128f, 0x01a0, 0x0400 }, ++ { 0xfc18, 0xf5ea, 0x0e00, 0x2000 }, ++ { 0x0e00, 0xf321, 0xfee1, 0x2000 }, ++ } ++}; ++ ++static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi, ++ const u16 coeffs[3][4]) ++{ ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ ++ HDMI_WRITE(HDMI_CSC_12_11, (coeffs[0][1] << 16) | coeffs[0][0]); ++ HDMI_WRITE(HDMI_CSC_14_13, (coeffs[0][3] << 16) | coeffs[0][2]); ++ HDMI_WRITE(HDMI_CSC_22_21, (coeffs[1][1] << 16) | coeffs[1][0]); ++ HDMI_WRITE(HDMI_CSC_24_23, (coeffs[1][3] << 16) | coeffs[1][2]); ++ HDMI_WRITE(HDMI_CSC_32_31, (coeffs[2][1] << 16) | coeffs[2][0]); ++ HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]); ++} ++ ++static void vc5_hdmi_set_csc_coeffs_swap(struct vc4_hdmi *vc4_hdmi, ++ const u16 coeffs[3][4]) ++{ ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ ++ /* YUV444 needs the CSC matrices using the channels in a different order */ ++ HDMI_WRITE(HDMI_CSC_12_11, (coeffs[2][1] << 16) | coeffs[2][0]); ++ HDMI_WRITE(HDMI_CSC_14_13, (coeffs[2][3] << 16) | coeffs[2][2]); ++ HDMI_WRITE(HDMI_CSC_22_21, (coeffs[0][1] << 16) | coeffs[0][0]); ++ HDMI_WRITE(HDMI_CSC_24_23, (coeffs[0][3] << 16) | coeffs[0][2]); ++ HDMI_WRITE(HDMI_CSC_32_31, (coeffs[1][1] << 16) | coeffs[1][0]); ++ HDMI_WRITE(HDMI_CSC_34_33, (coeffs[1][3] << 16) | coeffs[1][2]); ++} ++ ++static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, ++ struct drm_connector_state *state, ++ const struct drm_display_mode *mode) ++{ ++ struct vc4_hdmi_connector_state *vc4_state = ++ conn_state_to_vc4_hdmi_conn_state(state); ++ unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, mode) ? 0 : 1; ++ const u16 (*csc)[4]; ++ unsigned long flags; ++ u32 if_cfg = 0; ++ u32 if_xbar = 0x543210; ++ u32 csc_chan_ctl = 0; ++ u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, ++ VC5_MT_CP_CSC_CTL_MODE); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ ++ switch (vc4_state->output_format) { ++ case VC4_HDMI_OUTPUT_YUV444: ++ case VC4_HDMI_OUTPUT_YUV422: ++ switch (state->colorspace) { ++ default: ++ case DRM_MODE_COLORIMETRY_NO_DATA: ++ case DRM_MODE_COLORIMETRY_BT709_YCC: ++ case DRM_MODE_COLORIMETRY_XVYCC_709: ++ case DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED: ++ case DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT: ++ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt709[lim_range]; ++ break; ++ case DRM_MODE_COLORIMETRY_SMPTE_170M_YCC: ++ case DRM_MODE_COLORIMETRY_XVYCC_601: ++ case DRM_MODE_COLORIMETRY_SYCC_601: ++ case DRM_MODE_COLORIMETRY_OPYCC_601: ++ case DRM_MODE_COLORIMETRY_BT601_YCC: ++ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt601[lim_range]; ++ break; ++ case DRM_MODE_COLORIMETRY_BT2020_CYCC: ++ case DRM_MODE_COLORIMETRY_BT2020_YCC: ++ case DRM_MODE_COLORIMETRY_BT2020_RGB: ++ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65: ++ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER: ++ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt2020[lim_range]; ++ break; ++ } ++ ++ if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { ++ csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, ++ VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) | ++ VC5_MT_CP_CSC_CTL_USE_444_TO_422 | ++ VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION; ++ ++ csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE, ++ VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP); ++ ++ if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY, ++ VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422); ++ ++ vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc); ++ } else { ++ vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc); ++ } ++ ++ break; ++ ++ case VC4_HDMI_OUTPUT_RGB: ++ if_xbar = 0x354021; ++ ++ vc5_hdmi_set_csc_coeffs(vc4_hdmi, ++ vc5_hdmi_csc_full_rgb_to_rgb[lim_range]); ++ break; ++ ++ default: ++ break; ++ } ++ ++ HDMI_WRITE(HDMI_VEC_INTERFACE_CFG, if_cfg); ++ HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, if_xbar); ++ HDMI_WRITE(HDMI_CSC_CHANNEL_CTL, csc_chan_ctl); ++ HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++} ++ ++static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ++ struct drm_connector_state *state, ++ struct drm_display_mode *mode) ++{ bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; -@@ -517,12 +764,12 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - VC4_HDMI_VERTA_VFP) | - VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); - u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | -- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + -+ interlaced, - VC4_HDMI_VERTB_VBP)); - u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; + bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; +@@ -529,6 +1214,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end - -- interlaced, -+ mode->crtc_vsync_end, + mode->crtc_vsync_end, VC4_HDMI_VERTB_VBP)); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_HORZA, -@@ -548,7 +795,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | +@@ -552,10 +1240,16 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); } + static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + struct drm_connector_state *state, struct drm_display_mode *mode) { ++ const struct vc4_hdmi_connector_state *vc4_state = ++ conn_state_to_vc4_hdmi_conn_state(state); bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; -@@ -561,13 +810,16 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; + bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; +@@ -565,16 +1259,21 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, VC5_HDMI_VERTA_VFP) | VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); - u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | +- u32 vertb = (VC4_SET_FIELD(mode->htotal >> (2 - pixel_rep), +- VC5_HDMI_VERTB_VSPO) | - VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, ++ u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | + VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + + interlaced, VC4_HDMI_VERTB_VBP)); u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end - -- interlaced, +- mode->crtc_vsync_end - interlaced, + mode->crtc_vsync_end, VC4_HDMI_VERTB_VBP)); ++ unsigned long flags; + unsigned char gcp; + bool gcp_en; + u32 reg; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); +- HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); HDMI_WRITE(HDMI_HORZA, -@@ -593,6 +845,44 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) | + (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) | +@@ -598,14 +1297,66 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); -+ switch (state->max_bpc) { ++ switch (vc4_state->output_bpc) { + case 12: + gcp = 6; + gcp_en = true; @@ -59682,6 +62996,15 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + break; + } + ++ /* ++ * YCC422 is always 36-bit and not considered deep colour so ++ * doesn't signal in GCP ++ */ ++ if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { ++ gcp = 4; ++ gcp_en = false; ++ } ++ + reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1); + reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK | + VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK); @@ -59705,9 +63028,42 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + HDMI_WRITE(HDMI_MISC_CONTROL, reg); + HDMI_WRITE(HDMI_CLOCK_STOP, 0); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); } -@@ -620,11 +910,17 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) + static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; + u32 drift; + int ret; + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + drift = HDMI_READ(HDMI_FIFO_CTL); + drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; + +@@ -613,133 +1364,164 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + usleep_range(1000, 1100); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & + VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); + WARN_ONCE(ret, "Timeout waiting for " "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } @@ -59723,13 +63079,18 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + drm_atomic_get_new_connector_state(state, connector); + struct vc4_hdmi_connector_state *vc4_conn_state = + conn_state_to_vc4_hdmi_conn_state(conn_state); -+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; ++ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + unsigned long bvb_rate, pixel_rate, hsm_rate; ++ unsigned long flags; int ret; ++ mutex_lock(&vc4_hdmi->mutex); ++ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); -@@ -633,65 +929,51 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) - return; + if (ret < 0) { + DRM_ERROR("Failed to retain power domain: %d\n", ret); +- return; ++ goto out; } - pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1); @@ -59814,16 +63175,22 @@ index ee293f061f0a..f1adaa9dc5f3 100644 if (vc4_hdmi->variant->phy_init) - vc4_hdmi->variant->phy_init(vc4_hdmi, mode); + vc4_hdmi->variant->phy_init(vc4_hdmi, vc4_conn_state); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | -@@ -699,10 +981,24 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) + VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ if (vc4_hdmi->variant->set_timings) - vc4_hdmi->variant->set_timings(vc4_hdmi, mode); + vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); + ++ mutex_unlock(&vc4_hdmi->mutex); ++ + return; + +err_remove_bvb_req: @@ -59835,6 +63202,8 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + clk_disable_unprepare(vc4_hdmi->pixel_clock); +err_runtime_pm: + pm_runtime_put(&vc4_hdmi->pdev->dev); ++out: ++ mutex_unlock(&vc4_hdmi->mutex); + return; } @@ -59842,95 +63211,387 @@ index ee293f061f0a..f1adaa9dc5f3 100644 +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { - struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); -@@ -724,7 +1020,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) +- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; +- struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ struct drm_connector *connector = &vc4_hdmi->connector; ++ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; ++ struct drm_connector_state *conn_state = ++ drm_atomic_get_new_connector_state(state, connector); ++ unsigned long flags; + +- if (vc4_encoder->hdmi_monitor && +- drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { +- if (vc4_hdmi->variant->csc_setup) +- vc4_hdmi->variant->csc_setup(vc4_hdmi, true); +- +- vc4_encoder->limited_rgb_range = true; +- } else { +- if (vc4_hdmi->variant->csc_setup) +- vc4_hdmi->variant->csc_setup(vc4_hdmi, false); ++ mutex_lock(&vc4_hdmi->mutex); + +- vc4_encoder->limited_rgb_range = false; +- } ++ if (vc4_hdmi->variant->csc_setup) ++ vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ ++ mutex_unlock(&vc4_hdmi->mutex); } -static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { - struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; +- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -@@ -735,6 +1032,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) ++ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; ++ unsigned long flags; + int ret; ++ mutex_lock(&vc4_hdmi->mutex); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ HDMI_WRITE(HDMI_VID_CTL, VC4_HD_VID_CTL_ENABLE | + VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_UNDERFLOW_ENABLE | VC4_HD_VID_CTL_FRAME_COUNTER_RESET | (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | -@@ -780,6 +1078,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) +@@ -753,6 +1535,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) + HDMI_READ(HDMI_SCHEDULER_CONTROL) | + VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) & + VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000); + WARN_ONCE(ret, "Timeout waiting for " +@@ -765,6 +1549,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) + HDMI_READ(HDMI_SCHEDULER_CONTROL) & + ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & + VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000); + WARN_ONCE(ret, "Timeout waiting for " +@@ -772,6 +1558,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) + } + + if (vc4_encoder->hdmi_monitor) { ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & + VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); + HDMI_WRITE(HDMI_SCHEDULER_CONTROL, +@@ -781,14 +1569,245 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, + VC4_HDMI_RAM_PACKET_ENABLE); + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ vc4_hdmi->output_enabled = true; ++ + vc4_hdmi_set_infoframes(encoder); } vc4_hdmi_recenter_fifo(vc4_hdmi); + vc4_hdmi_enable_scrambling(encoder); ++ ++ mutex_unlock(&vc4_hdmi->mutex); + } + +-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) ++static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) + { ++ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ struct vc4_hdmi_connector_state *vc4_state = ++ conn_state_to_vc4_hdmi_conn_state(conn_state); ++ ++ mutex_lock(&vc4_hdmi->mutex); ++ vc4_hdmi->output_bpc = vc4_state->output_bpc; ++ vc4_hdmi->output_format = vc4_state->output_format; ++ vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb; ++ memcpy(&vc4_hdmi->saved_adjusted_mode, ++ &crtc_state->adjusted_mode, ++ sizeof(vc4_hdmi->saved_adjusted_mode)); ++ mutex_unlock(&vc4_hdmi->mutex); ++} ++ ++static bool ++vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode, ++ unsigned int format, unsigned int bpc) ++{ ++ struct drm_device *dev = vc4_hdmi->connector.dev; ++ u8 vic = drm_match_cea_mode(mode); ++ ++ if (vic == 1 && bpc != 8) { ++ drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); ++ return false; ++ } ++ ++ if (!info->is_hdmi && ++ (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) { ++ drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n"); ++ return false; ++ } ++ ++ switch (format) { ++ case VC4_HDMI_OUTPUT_RGB: ++ drm_dbg(dev, "RGB Format, checking the constraints.\n"); ++ ++ if (bpc == 10 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)) { ++ drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); ++ return false; ++ } ++ ++ if (bpc == 12 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36)) { ++ drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); ++ return false; ++ } ++ ++ drm_dbg(dev, "RGB format supported in that configuration.\n"); ++ ++ return true; ++ ++ case VC4_HDMI_OUTPUT_YUV422: ++ drm_dbg(dev, "YUV422 format, checking the constraints.\n"); ++ ++ if (!(info->color_formats & DRM_COLOR_FORMAT_YCRCB422)) { ++ drm_dbg(dev, "Sink doesn't support YUV422.\n"); ++ return false; ++ } ++ ++ if (bpc != 12) { ++ drm_dbg(dev, "YUV422 only supports 12 bpc.\n"); ++ return false; ++ } ++ ++ drm_dbg(dev, "YUV422 format supported in that configuration.\n"); ++ ++ return true; ++ ++ case VC4_HDMI_OUTPUT_YUV444: ++ drm_dbg(dev, "YUV444 format, checking the constraints.\n"); ++ ++ if (!(info->color_formats & DRM_COLOR_FORMAT_YCRCB444)) { ++ drm_dbg(dev, "Sink doesn't support YUV444.\n"); ++ return false; ++ } ++ ++ if (bpc == 10 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30)) { ++ drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); ++ return false; ++ } ++ ++ if (bpc == 12 && !(info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36)) { ++ drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); ++ return false; ++ } ++ ++ drm_dbg(dev, "YUV444 format supported in that configuration.\n"); ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++static enum drm_mode_status ++vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, ++ unsigned long long clock) ++{ ++ const struct drm_connector *connector = &vc4_hdmi->connector; ++ const struct drm_display_info *info = &connector->display_info; ++ ++ if (clock > vc4_hdmi->variant->max_pixel_clock) ++ return MODE_CLOCK_HIGH; ++ ++ if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK) ++ return MODE_CLOCK_HIGH; ++ ++ if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000)) ++ return MODE_CLOCK_HIGH; ++ ++ return MODE_OK; ++} ++ ++static unsigned long long ++vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, ++ unsigned int bpc, ++ enum vc4_hdmi_output_format fmt) ++{ ++ unsigned long long clock = mode->clock * 1000; ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) ++ clock = clock * 2; ++ ++ if (fmt == VC4_HDMI_OUTPUT_YUV422) ++ bpc = 8; ++ ++ return clock * bpc / 8; ++} ++ ++static int ++vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *vc4_state, ++ const struct drm_display_mode *mode, ++ unsigned int bpc, unsigned int fmt) ++{ ++ unsigned long long clock; ++ ++ clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); ++ if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK) ++ return -EINVAL; ++ ++ vc4_state->pixel_rate = clock; ++ ++ return 0; ++} ++ ++static int ++vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *vc4_state, ++ const struct drm_display_mode *mode, ++ unsigned int bpc) ++{ ++ struct drm_device *dev = vc4_hdmi->connector.dev; ++ const struct drm_connector *connector = &vc4_hdmi->connector; ++ const struct drm_display_info *info = &connector->display_info; ++ unsigned int format; ++ ++ drm_dbg(dev, "Trying with an RGB output\n"); ++ ++ format = VC4_HDMI_OUTPUT_RGB; ++ if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { ++ int ret; ++ ++ ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, ++ mode, bpc, format); ++ if (!ret) { ++ vc4_state->output_format = format; ++ return 0; ++ } ++ } ++ ++ drm_dbg(dev, "Failed, Trying with an YUV422 output\n"); ++ ++ format = VC4_HDMI_OUTPUT_YUV422; ++ if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { ++ int ret; ++ ++ ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, ++ mode, bpc, format); ++ if (!ret) { ++ vc4_state->output_format = format; ++ return 0; ++ } ++ } ++ ++ drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n"); ++ ++ return -EINVAL; ++} ++ ++static int ++vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *vc4_state, ++ const struct drm_display_mode *mode) ++{ ++ struct drm_device *dev = vc4_hdmi->connector.dev; ++ struct drm_connector_state *conn_state = &vc4_state->base; ++ unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); ++ unsigned int bpc; ++ int ret; ++ ++ for (bpc = max_bpc; bpc >= 8; bpc -= 2) { ++ drm_dbg(dev, "Trying with a %d bpc output\n", bpc); ++ ++ ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state, ++ mode, bpc); ++ if (ret) ++ continue; ++ ++ vc4_state->output_bpc = bpc; ++ ++ drm_dbg(dev, ++ "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", ++ mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), ++ vc4_state->output_bpc, ++ vc4_hdmi_output_fmt_str(vc4_state->output_format), ++ vc4_state->pixel_rate); ++ ++ break; ++ } ++ ++ return ret; } - static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) -@@ -793,12 +1092,14 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, + #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL +@@ -798,10 +1817,15 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { + struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state); struct drm_display_mode *mode = &crtc_state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ struct drm_connector *connector = &vc4_hdmi->connector; ++ struct drm_connector_state *old_conn_state = drm_atomic_get_old_connector_state(conn_state->state, connector); ++ struct vc4_hdmi_connector_state *old_vc4_state = conn_state_to_vc4_hdmi_conn_state(old_conn_state); unsigned long long pixel_rate = mode->clock * 1000; unsigned long long tmds_rate; ++ int ret; if (vc4_hdmi->variant->unsupported_odd_h_timings && -+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && - ((mode->hdisplay % 2) || (mode->hsync_start % 2) || - (mode->hsync_end % 2) || (mode->htotal % 2))) - return -EINVAL; -@@ -817,12 +1118,25 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, + !(mode->flags & DRM_MODE_FLAG_DBLCLK) && +@@ -823,11 +1847,14 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, pixel_rate = mode->clock * 1000; } -+ if (conn_state->max_bpc == 12) { -+ pixel_rate = pixel_rate * 150; -+ do_div(pixel_rate, 100); -+ } else if (conn_state->max_bpc == 10) { -+ pixel_rate = pixel_rate * 125; -+ do_div(pixel_rate, 100); -+ } -+ - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - pixel_rate = pixel_rate * 2; +- if (mode->flags & DRM_MODE_FLAG_DBLCLK) +- pixel_rate = pixel_rate * 2; ++ ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode); ++ if (ret) ++ return ret; - if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) - return -EINVAL; +- if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) +- return -EINVAL; ++ /* vc4_hdmi_encoder_compute_config may have changed output_bpc and/or output_format */ ++ if (vc4_state->output_bpc != old_vc4_state->output_bpc || ++ vc4_state->output_format != old_vc4_state->output_format) ++ crtc_state->mode_changed = true; -+ if (vc4_hdmi->disable_4kp60 && (pixel_rate > HDMI_14_MAX_TMDS_CLK)) -+ return -EINVAL; -+ -+ vc4_state->pixel_rate = pixel_rate; -+ return 0; } - -@@ -833,6 +1147,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - - if (vc4_hdmi->variant->unsupported_odd_h_timings && -+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && - ((mode->hdisplay % 2) || (mode->hsync_start % 2) || +@@ -844,19 +1871,48 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, (mode->hsync_end % 2) || (mode->htotal % 2))) return MODE_H_ILLEGAL; -@@ -840,6 +1155,9 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, - if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) - return MODE_CLOCK_HIGH; -+ if (vc4_hdmi->disable_4kp60 && vc4_hdmi_mode_needs_scrambling(mode)) -+ return MODE_CLOCK_HIGH; -+ - return MODE_OK; +- if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) +- return MODE_CLOCK_HIGH; +- +- return MODE_OK; ++ return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000); } -@@ -850,6 +1168,39 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { - .enable = vc4_hdmi_encoder_enable, + static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { + .atomic_check = vc4_hdmi_encoder_atomic_check, ++ .atomic_mode_set = vc4_hdmi_encoder_atomic_mode_set, + .mode_valid = vc4_hdmi_encoder_mode_valid, +- .disable = vc4_hdmi_encoder_disable, +- .enable = vc4_hdmi_encoder_enable, }; +static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) @@ -59969,15 +63630,29 @@ index ee293f061f0a..f1adaa9dc5f3 100644 static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) { int i; -@@ -875,12 +1226,13 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) +@@ -881,33 +1937,49 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) + return channel_map; } ++static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi) ++{ ++ unsigned long flags; ++ u32 hotplug; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ hotplug = HDMI_READ(HDMI_HOTPLUG); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ ++ return !!(hotplug & VC4_HDMI_HOTPLUG_CONNECTED); ++} ++ /* HDMI audio codec callbacks */ -static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) +static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, + unsigned int samplerate) { u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); ++ unsigned long flags; unsigned long n, m; - rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate, @@ -59985,31 +63660,43 @@ index ee293f061f0a..f1adaa9dc5f3 100644 VC4_HD_MAI_SMP_N_MASK >> VC4_HD_MAI_SMP_N_SHIFT, (VC4_HD_MAI_SMP_M_MASK >> -@@ -892,12 +1244,11 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) + VC4_HD_MAI_SMP_M_SHIFT) + 1, + &n, &m); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_MAI_SMP, + VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) | VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); } -static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi) +static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) { - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_crtc *crtc = encoder->crtc; - const struct drm_display_mode *mode = &crtc->state->adjusted_mode; +- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; +- struct drm_crtc *crtc = encoder->crtc; +- const struct drm_display_mode *mode = &crtc->state->adjusted_mode; - u32 samplerate = vc4_hdmi->audio.samplerate; ++ const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; u32 n, cts; u64 tmp; -@@ -926,18 +1277,10 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) ++ lockdep_assert_held(&vc4_hdmi->mutex); ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ + n = 128 * samplerate / 1000; + tmp = (u64)(mode->clock * 1000) * n; + do_div(tmp, 128 * samplerate); +@@ -933,36 +2005,48 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) return snd_soc_card_get_drvdata(card); } -static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -+static int vc4_hdmi_audio_startup(struct device *dev, void *data) ++static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi) { - struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); -+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; +- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_connector *connector = &vc4_hdmi->connector; - int ret; - @@ -60017,46 +63704,82 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - return -EINVAL; - - vc4_hdmi->audio.substream = substream; ++ lockdep_assert_held(&vc4_hdmi->mutex); /* - * If the HDMI encoder hasn't probed, or the encoder is -@@ -947,15 +1290,18 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, - VC4_HDMI_RAM_PACKET_ENABLE)) - return -ENODEV; - +- * If the HDMI encoder hasn't probed, or the encoder is +- * currently in DVI mode, treat the codec dai as missing. ++ * If the encoder is currently in DVI mode, treat the codec DAI ++ * as missing. + */ +- if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & +- VC4_HDMI_RAM_PACKET_ENABLE)) +- return -ENODEV; +- - ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld); - if (ret) - return ret; -+ vc4_hdmi->audio.streaming = true; ++ if (!vc4_hdmi->encoder.hdmi_monitor) ++ return false; - return 0; --} ++ return true; + } + +-static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ++static int vc4_hdmi_audio_startup(struct device *dev, void *data) + { ++ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); ++ unsigned long flags; ++ ++ mutex_lock(&vc4_hdmi->mutex); ++ ++ if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) { ++ mutex_unlock(&vc4_hdmi->mutex); ++ return -ENODEV; ++ } ++ ++ vc4_hdmi->audio.streaming = true; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_MAI_CTL, + VC4_HD_MAI_CTL_RESET | + VC4_HD_MAI_CTL_FLUSH | + VC4_HD_MAI_CTL_DLATE | + VC4_HD_MAI_CTL_ERRORE | + VC4_HD_MAI_CTL_ERRORF); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + if (vc4_hdmi->variant->phy_rng_enable) + vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); - --static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) --{ ++ ++ mutex_unlock(&vc4_hdmi->mutex); ++ return 0; } -@@ -966,7 +1312,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) +@@ -970,60 +2054,133 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) + { + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; + struct device *dev = &vc4_hdmi->pdev->dev; ++ unsigned long flags; int ret; ++ lockdep_assert_held(&vc4_hdmi->mutex); ++ vc4_hdmi->audio.streaming = false; - ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO); + ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO, false); if (ret) dev_err(dev, "Failed to stop audio infoframe: %d\n", ret); -@@ -975,48 +1321,96 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET); + HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF); HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); } -static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream, @@ -60065,22 +63788,31 @@ index ee293f061f0a..f1adaa9dc5f3 100644 { - struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); ++ unsigned long flags; - if (substream != vc4_hdmi->audio.substream) - return; ++ mutex_lock(&vc4_hdmi->mutex); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + HDMI_WRITE(HDMI_MAI_CTL, + VC4_HD_MAI_CTL_DLATE | + VC4_HD_MAI_CTL_ERRORE | + VC4_HD_MAI_CTL_ERRORF); - ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + if (vc4_hdmi->variant->phy_rng_disable) + vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); -+ + + vc4_hdmi->audio.streaming = false; vc4_hdmi_audio_reset(vc4_hdmi); -+} - vc4_hdmi->audio.substream = NULL; ++ mutex_unlock(&vc4_hdmi->mutex); ++} ++ +static int sample_rate_to_mai_fmt(int samplerate) +{ + switch (samplerate) { @@ -60133,6 +63865,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - struct device *dev = &vc4_hdmi->pdev->dev; + unsigned int sample_rate = params->sample_rate; + unsigned int channels = params->channels; ++ unsigned long flags; u32 audio_packet_config, channel_mask; u32 channel_map; - @@ -60144,26 +63877,33 @@ index ee293f061f0a..f1adaa9dc5f3 100644 dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__, - params_rate(params), params_width(params), - params_channels(params)); -- ++ sample_rate, params->sample_width, channels); + - vc4_hdmi->audio.channels = params_channels(params); - vc4_hdmi->audio.samplerate = params_rate(params); -+ sample_rate, params->sample_width, channels); ++ mutex_lock(&vc4_hdmi->mutex); - HDMI_WRITE(HDMI_MAI_CTL, +- HDMI_WRITE(HDMI_MAI_CTL, - VC4_HD_MAI_CTL_RESET | - VC4_HD_MAI_CTL_FLUSH | - VC4_HD_MAI_CTL_DLATE | - VC4_HD_MAI_CTL_ERRORE | - VC4_HD_MAI_CTL_ERRORF); -- ++ if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) { ++ mutex_unlock(&vc4_hdmi->mutex); ++ return -EINVAL; ++ } ++ ++ vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); + - vc4_hdmi_audio_set_mai_clock(vc4_hdmi); ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ HDMI_WRITE(HDMI_MAI_CTL, + VC4_SET_FIELD(channels, VC4_HD_MAI_CTL_CHNUM) | + VC4_HD_MAI_CTL_WHOLSMP | + VC4_HD_MAI_CTL_CHALIGN | + VC4_HD_MAI_CTL_ENABLE); + -+ vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); -+ + mai_sample_rate = sample_rate_to_mai_fmt(sample_rate); + if (params->iec.status[0] & IEC958_AES0_NONAUDIO && + params->channels == 8) @@ -60178,7 +63918,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 /* The B frame identifier should match the value used by alsa-lib (8) */ audio_packet_config = -@@ -1024,124 +1418,33 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, +@@ -1031,7 +2188,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS | VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER); @@ -60187,28 +63927,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 audio_packet_config |= VC4_SET_FIELD(channel_mask, VC4_HDMI_AUDIO_PACKET_CEA_MASK); -- /* Set the MAI threshold. This logic mimics the firmware's. */ -- if (vc4_hdmi->audio.samplerate > 96000) { -- HDMI_WRITE(HDMI_MAI_THR, -- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) | -- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); -- } else if (vc4_hdmi->audio.samplerate > 48000) { -- HDMI_WRITE(HDMI_MAI_THR, -- VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) | -- VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); -- } else { -- HDMI_WRITE(HDMI_MAI_THR, -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) | -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW)); -- } -+ /* Set the MAI threshold */ -+ HDMI_WRITE(HDMI_MAI_THR, -+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICHIGH) | -+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICLOW) | -+ VC4_SET_FIELD(0x06, VC4_HD_MAI_THR_DREQHIGH) | -+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_DREQLOW)); +@@ -1044,101 +2201,26 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, HDMI_WRITE(HDMI_MAI_CONFIG, VC4_HDMI_MAI_CONFIG_BIT_REVERSE | @@ -60219,14 +63938,13 @@ index ee293f061f0a..f1adaa9dc5f3 100644 HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map); HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config); - vc4_hdmi_set_n_cts(vc4_hdmi); -+ vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate); - -+ memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); - vc4_hdmi_set_audio_infoframe(encoder); - return 0; - } +- vc4_hdmi_set_audio_infoframe(encoder); ++ vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate); +- return 0; +-} +- -static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ @@ -60235,7 +63953,8 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - vc4_hdmi->audio.streaming = true; -- ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + - if (vc4_hdmi->variant->phy_rng_enable) - vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); - @@ -60292,13 +64011,17 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component); - struct drm_connector *connector = &vc4_hdmi->connector; -- ++ memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); ++ if (vc4_hdmi->output_enabled) ++ vc4_hdmi_set_audio_infoframe(encoder); + - memcpy(ucontrol->value.bytes.data, connector->eld, - sizeof(connector->eld)); -- -- return 0; --} -- ++ mutex_unlock(&vc4_hdmi->mutex); + + return 0; + } + -static const struct snd_kcontrol_new vc4_hdmi_audio_controls[] = { - { - .access = SNDRV_CTL_ELEM_ACCESS_READ | @@ -60313,19 +64036,22 @@ index ee293f061f0a..f1adaa9dc5f3 100644 static const struct snd_soc_dapm_widget vc4_hdmi_audio_widgets[] = { SND_SOC_DAPM_OUTPUT("TX"), }; -@@ -1152,8 +1455,6 @@ static const struct snd_soc_dapm_route vc4_hdmi_audio_routes[] = { +@@ -1149,38 +2231,14 @@ static const struct snd_soc_dapm_route vc4_hdmi_audio_routes[] = { static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = { .name = "vc4-hdmi-codec-dai-component", - .controls = vc4_hdmi_audio_controls, - .num_controls = ARRAY_SIZE(vc4_hdmi_audio_controls), - .dapm_widgets = vc4_hdmi_audio_widgets, - .num_dapm_widgets = ARRAY_SIZE(vc4_hdmi_audio_widgets), - .dapm_routes = vc4_hdmi_audio_routes, -@@ -1164,28 +1465,6 @@ static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = { - .non_legacy_dai_naming = 1, - }; - +- .dapm_widgets = vc4_hdmi_audio_widgets, +- .num_dapm_widgets = ARRAY_SIZE(vc4_hdmi_audio_widgets), +- .dapm_routes = vc4_hdmi_audio_routes, +- .num_dapm_routes = ARRAY_SIZE(vc4_hdmi_audio_routes), +- .idle_bias_on = 1, +- .use_pmdown_time = 1, +- .endianness = 1, +- .non_legacy_dai_naming = 1, +-}; +- -static const struct snd_soc_dai_ops vc4_hdmi_audio_dai_ops = { - .startup = vc4_hdmi_audio_startup, - .shutdown = vc4_hdmi_audio_shutdown, @@ -60346,12 +64072,18 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, - }, --}; -- - static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = { - .name = "vc4-hdmi-cpu-dai-component", ++ .dapm_widgets = vc4_hdmi_audio_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(vc4_hdmi_audio_widgets), ++ .dapm_routes = vc4_hdmi_audio_routes, ++ .num_dapm_routes = ARRAY_SIZE(vc4_hdmi_audio_routes), ++ .idle_bias_on = 1, ++ .use_pmdown_time = 1, ++ .endianness = 1, ++ .non_legacy_dai_naming = 1, }; -@@ -1212,7 +1491,6 @@ static struct snd_soc_dai_driver vc4_hdmi_audio_cpu_dai_drv = { + + static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = { +@@ -1209,7 +2267,6 @@ static struct snd_soc_dai_driver vc4_hdmi_audio_cpu_dai_drv = { SNDRV_PCM_RATE_192000, .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, }, @@ -60359,7 +64091,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 }; static const struct snd_dmaengine_pcm_config pcm_conf = { -@@ -1220,6 +1498,31 @@ static const struct snd_dmaengine_pcm_config pcm_conf = { +@@ -1217,6 +2274,33 @@ static const struct snd_dmaengine_pcm_config pcm_conf = { .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, }; @@ -60370,7 +64102,9 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + struct drm_connector *connector = &vc4_hdmi->connector; + ++ mutex_lock(&vc4_hdmi->mutex); + memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); ++ mutex_unlock(&vc4_hdmi->mutex); + + return 0; +} @@ -60391,26 +64125,24 @@ index ee293f061f0a..f1adaa9dc5f3 100644 static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) { const struct vc4_hdmi_register *mai_data = -@@ -1227,13 +1530,16 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) +@@ -1224,11 +2308,14 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; struct snd_soc_card *card = &vc4_hdmi->audio.card; struct device *dev = &vc4_hdmi->pdev->dev; + struct platform_device *codec_pdev; const __be32 *addr; - int index; +- int index, len; ++ int index; int ret; + int len; -- if (!of_find_property(dev->of_node, "dmas", NULL)) { +- if (!of_find_property(dev->of_node, "dmas", &len) || !len) { + 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"); + "'dmas' DT property is missing or empty, no HDMI audio\n"); return 0; - } - -@@ -1273,12 +1579,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) +@@ -1270,12 +2357,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) return ret; } @@ -60430,7 +64162,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 } dai_link->cpus = &vc4_hdmi->audio.cpu; -@@ -1291,9 +1598,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) +@@ -1288,9 +2376,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) dai_link->name = "MAI"; dai_link->stream_name = "MAI PCM"; @@ -60442,7 +64174,14 @@ index ee293f061f0a..f1adaa9dc5f3 100644 dai_link->platforms->name = dev_name(dev); card->dai_link = dai_link; -@@ -1319,16 +1626,77 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) +@@ -1310,22 +2398,83 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) + snd_soc_card_set_drvdata(card, vc4_hdmi); + ret = devm_snd_soc_register_card(dev, card); + if (ret) +- dev_err(dev, "Could not register sound card: %d\n", ret); ++ dev_err_probe(dev, ret, "Could not register sound card.\n"); + + return ret; } @@ -60503,14 +64242,9 @@ index ee293f061f0a..f1adaa9dc5f3 100644 #ifdef CONFIG_DRM_VC4_HDMI_CEC -static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) +static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv) - { - struct vc4_hdmi *vc4_hdmi = priv; - -- if (vc4_hdmi->cec_irq_was_rx) { -- if (vc4_hdmi->cec_rx_msg.len) -- cec_received_msg(vc4_hdmi->cec_adap, -- &vc4_hdmi->cec_rx_msg); -- } else if (vc4_hdmi->cec_tx_ok) { ++{ ++ struct vc4_hdmi *vc4_hdmi = priv; ++ + if (vc4_hdmi->cec_rx_msg.len) + cec_received_msg(vc4_hdmi->cec_adap, + &vc4_hdmi->cec_rx_msg); @@ -60519,14 +64253,19 @@ index ee293f061f0a..f1adaa9dc5f3 100644 +} + +static irqreturn_t vc4_cec_irq_handler_tx_thread(int irq, void *priv) -+{ -+ struct vc4_hdmi *vc4_hdmi = priv; -+ + { + struct vc4_hdmi *vc4_hdmi = priv; + +- if (vc4_hdmi->cec_irq_was_rx) { +- if (vc4_hdmi->cec_rx_msg.len) +- cec_received_msg(vc4_hdmi->cec_adap, +- &vc4_hdmi->cec_rx_msg); +- } else if (vc4_hdmi->cec_tx_ok) { + if (vc4_hdmi->cec_tx_ok) { cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); } else { -@@ -1342,6 +1710,19 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) +@@ -1339,12 +2488,27 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) return IRQ_HANDLED; } @@ -60546,15 +64285,24 @@ index ee293f061f0a..f1adaa9dc5f3 100644 static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) { struct drm_device *dev = vc4_hdmi->connector.dev; -@@ -1366,76 +1747,125 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) + struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; + unsigned int i; + ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ + msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> + VC4_HDMI_CEC_REC_WRD_CNT_SHIFT); + +@@ -1363,83 +2527,208 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) } } -+static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv) ++static irqreturn_t vc4_cec_irq_handler_tx_bare_locked(struct vc4_hdmi *vc4_hdmi) +{ -+ struct vc4_hdmi *vc4_hdmi = priv; + u32 cntrl1; + ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); + vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; + cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; @@ -60563,11 +64311,24 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + return IRQ_WAKE_THREAD; +} + -+static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv) ++static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv) +{ + struct vc4_hdmi *vc4_hdmi = priv; ++ irqreturn_t ret; ++ ++ spin_lock(&vc4_hdmi->hw_lock); ++ ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi); ++ spin_unlock(&vc4_hdmi->hw_lock); ++ ++ return ret; ++} ++ ++static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi) ++{ + u32 cntrl1; + ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ + vc4_hdmi->cec_rx_msg.len = 0; + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); + vc4_cec_read_msg(vc4_hdmi, cntrl1); @@ -60579,6 +64340,18 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + + return IRQ_WAKE_THREAD; +} ++ ++static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv) ++{ ++ struct vc4_hdmi *vc4_hdmi = priv; ++ irqreturn_t ret; ++ ++ spin_lock(&vc4_hdmi->hw_lock); ++ ret = vc4_cec_irq_handler_rx_bare_locked(vc4_hdmi); ++ spin_unlock(&vc4_hdmi->hw_lock); ++ ++ return ret; ++} + static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) { @@ -60593,6 +64366,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - vc4_hdmi->cec_rx_msg.len = 0; - cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); + ++ spin_lock(&vc4_hdmi->hw_lock); cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5); vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; - if (vc4_hdmi->cec_irq_was_rx) { @@ -60605,14 +64379,15 @@ index ee293f061f0a..f1adaa9dc5f3 100644 - cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; - } - HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); -- HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); + if (vc4_hdmi->cec_irq_was_rx) -+ ret = vc4_cec_irq_handler_rx_bare(irq, priv); ++ ret = vc4_cec_irq_handler_rx_bare_locked(vc4_hdmi); + else -+ ret = vc4_cec_irq_handler_tx_bare(irq, priv); ++ ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi); ++ + HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); ++ spin_unlock(&vc4_hdmi->hw_lock); - return IRQ_WAKE_THREAD; -+ HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); + return ret; } @@ -60623,13 +64398,27 @@ index ee293f061f0a..f1adaa9dc5f3 100644 /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; - u32 val = HDMI_READ(HDMI_CEC_CNTRL_5); ++ unsigned long flags; + u32 val; + int ret; - ++ ++ /* ++ * NOTE: This function should really take vc4_hdmi->mutex, but doing so ++ * results in a reentrancy since cec_s_phys_addr_from_edid() called in ++ * .detect or .get_modes might call .adap_enable, which leads to this ++ * function being called with that mutex held. ++ * ++ * Concurrency is not an issue for the moment since we don't share any ++ * state with KMS, so we can ignore the lock for now, but we need to ++ * keep it in mind if we were to change that assumption. ++ */ ++ + ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); + if (ret) + return ret; + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + + val = HDMI_READ(HDMI_CEC_CNTRL_5); val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET | VC4_HDMI_CEC_CNT_TO_4700_US_MASK | @@ -60682,12 +64471,28 @@ index ee293f061f0a..f1adaa9dc5f3 100644 HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); - } else { + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + return 0; +} + +static int vc4_hdmi_cec_disable(struct cec_adapter *adap) +{ + struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); ++ unsigned long flags; ++ ++ /* ++ * NOTE: This function should really take vc4_hdmi->mutex, but doing so ++ * results in a reentrancy since cec_s_phys_addr_from_edid() called in ++ * .detect or .get_modes might call .adap_enable, which leads to this ++ * function being called with that mutex held. ++ * ++ * Concurrency is not an issue for the moment since we don't share any ++ * state with KMS, so we can ignore the lock for now, but we need to ++ * keep it in mind if we were to change that assumption. ++ */ ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + + if (!vc4_hdmi->variant->external_irq_controller) HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC); @@ -60698,6 +64503,8 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + HDMI_WRITE(HDMI_CEC_CNTRL_5, HDMI_READ(HDMI_CEC_CNTRL_5) | + VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); + ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + pm_runtime_put(&vc4_hdmi->pdev->dev); + return 0; @@ -60714,12 +64521,74 @@ index ee293f061f0a..f1adaa9dc5f3 100644 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); -@@ -1487,11 +1917,14 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) ++ unsigned long flags; ++ ++ /* ++ * NOTE: This function should really take vc4_hdmi->mutex, but doing so ++ * results in a reentrancy since cec_s_phys_addr_from_edid() called in ++ * .detect or .get_modes might call .adap_enable, which leads to this ++ * function being called with that mutex held. ++ * ++ * Concurrency is not an issue for the moment since we don't share any ++ * state with KMS, so we can ignore the lock for now, but we need to ++ * keep it in mind if we were to change that assumption. ++ */ + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_CEC_CNTRL_1, + (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | + (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + return 0; + } + +@@ -1448,14 +2737,28 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + { + struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct drm_device *dev = vc4_hdmi->connector.dev; ++ unsigned long flags; + u32 val; + unsigned int i; + ++ /* ++ * NOTE: This function should really take vc4_hdmi->mutex, but doing so ++ * results in a reentrancy since cec_s_phys_addr_from_edid() called in ++ * .detect or .get_modes might call .adap_enable, which leads to this ++ * function being called with that mutex held. ++ * ++ * Concurrency is not an issue for the moment since we don't share any ++ * state with KMS, so we can ignore the lock for now, but we need to ++ * keep it in mind if we were to change that assumption. ++ */ ++ + if (msg->len > 16) { + drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); + return -ENOMEM; + } + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + for (i = 0; i < msg->len; i += 4) + HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2), + (msg->msg[i]) | +@@ -1471,6 +2774,9 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + val |= VC4_HDMI_CEC_START_XMIT_BEGIN; + + HDMI_WRITE(HDMI_CEC_CNTRL_1, val); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ + return 0; + } + +@@ -1484,11 +2790,14 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) { struct cec_connector_info conn_info; struct platform_device *pdev = vc4_hdmi->pdev; +- u32 value; + struct device *dev = &pdev->dev; - u32 value; ++ unsigned long flags; int ret; - if (!vc4_hdmi->variant->cec_available) @@ -60730,19 +64599,19 @@ index ee293f061f0a..f1adaa9dc5f3 100644 vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, vc4_hdmi, "vc4", -@@ -1504,8 +1937,6 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) +@@ -1501,28 +2810,49 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); - HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); - - value = HDMI_READ(HDMI_CEC_CNTRL_1); - /* Set the logical address to Unregistered */ - value |= VC4_HDMI_CEC_ADDR_MASK; -@@ -1513,19 +1944,47 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) - - vc4_hdmi_cec_update_clk_div(vc4_hdmi); - +- value = HDMI_READ(HDMI_CEC_CNTRL_1); +- /* Set the logical address to Unregistered */ +- value |= VC4_HDMI_CEC_ADDR_MASK; +- HDMI_WRITE(HDMI_CEC_CNTRL_1, value); +- +- vc4_hdmi_cec_update_clk_div(vc4_hdmi); +- - ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0), - vc4_cec_irq_handler, - vc4_cec_irq_handler_thread, 0, @@ -60764,7 +64633,9 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + if (ret) + goto err_remove_cec_rx_handler; + } else { ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + ret = request_threaded_irq(platform_get_irq(pdev, 0), + vc4_cec_irq_handler, @@ -60794,7 +64665,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 err_delete_cec_adap: cec_delete_adapter(vc4_hdmi->cec_adap); -@@ -1534,6 +1993,15 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) +@@ -1531,8 +2861,40 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) { @@ -60809,8 +64680,44 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + cec_unregister_adapter(vc4_hdmi->cec_adap); } ++ ++static int vc4_hdmi_cec_resume(struct vc4_hdmi *vc4_hdmi) ++{ ++ unsigned long flags; ++ u32 value; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ value = HDMI_READ(HDMI_CEC_CNTRL_1); ++ /* Set the logical address to Unregistered */ ++ value |= VC4_HDMI_CEC_ADDR_MASK; ++ HDMI_WRITE(HDMI_CEC_CNTRL_1, value); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ ++ vc4_hdmi_cec_update_clk_div(vc4_hdmi); ++ ++ if (!vc4_hdmi->variant->external_irq_controller) { ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ } ++ ++ return 0; ++} #else -@@ -1618,6 +2086,7 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) + static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) + { +@@ -1541,6 +2903,10 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) + + static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {}; + ++static int vc4_hdmi_cec_resume(struct vc4_hdmi *vc4_hdmi) ++{ ++ return 0; ++} + #endif + + static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, +@@ -1615,6 +2981,7 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return PTR_ERR(vc4_hdmi->hsm_clock); } vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; @@ -60818,7 +64725,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 return 0; } -@@ -1627,6 +2096,7 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) +@@ -1624,6 +2991,7 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) struct platform_device *pdev = vc4_hdmi->pdev; struct device *dev = &pdev->dev; struct resource *res; @@ -60826,7 +64733,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); if (!res) -@@ -1711,12 +2181,50 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) +@@ -1708,12 +3076,50 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return PTR_ERR(vc4_hdmi->audio_clock); } @@ -60877,15 +64784,49 @@ index ee293f061f0a..f1adaa9dc5f3 100644 return 0; } -@@ -1757,6 +2265,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) +@@ -1736,6 +3142,15 @@ static int vc4_hdmi_runtime_resume(struct device *dev) + if (ret) + return ret; + ++ if (vc4_hdmi->variant->reset) ++ vc4_hdmi->variant->reset(vc4_hdmi); ++ ++ ret = vc4_hdmi_cec_resume(vc4_hdmi); ++ if (ret) { ++ clk_disable_unprepare(vc4_hdmi->hsm_clock); ++ return ret; ++ } ++ + return 0; + } + #endif +@@ -1754,6 +3169,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); if (!vc4_hdmi) return -ENOMEM; ++ mutex_init(&vc4_hdmi->mutex); ++ spin_lock_init(&vc4_hdmi->hw_lock); + INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); dev_set_drvdata(dev, vc4_hdmi); encoder = &vc4_hdmi->encoder.base.base; -@@ -1806,6 +2315,52 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) +@@ -1766,6 +3184,15 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + vc4_hdmi->pdev = pdev; + vc4_hdmi->variant = variant; + ++ /* ++ * Since we don't know the state of the controller and its ++ * display (if any), let's assume it's always enabled. ++ * vc4_hdmi_disable_scrambling() will thus run at boot, make ++ * sure it's disabled, and avoid any inconsistency. ++ */ ++ if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) ++ vc4_hdmi->scdc_enabled = true; ++ + ret = variant->init_resources(vc4_hdmi); + if (ret) + return ret; +@@ -1803,6 +3230,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->disable_wifi_frequencies = of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); @@ -60897,14 +64838,13 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + vc4_hdmi->disable_4kp60 = true; + } + -+ /* -+ * If we boot without any cable connected to the HDMI connector, -+ * the firmware will skip the HSM initialization and leave it -+ * with a rate of 0, resulting in a bus lockup when we're -+ * accessing the registers even if it's enabled. -+ * -+ * Let's put a sensible default at runtime_resume so that we -+ * don't end up in this situation. + /* + * If we boot without any cable connected to the HDMI connector, + * the firmware will skip the HSM initialization and leave it +@@ -1811,13 +3246,29 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + * + * Let's put a sensible default at runtime_resume so that we + * don't end up in this situation. + * + * Strictly speaking we should be using clk_set_min_rate. + * However, the clk-bcm2835 clock driver favors clock rates @@ -60918,27 +64858,23 @@ index ee293f061f0a..f1adaa9dc5f3 100644 + * we're not at risk of having the first controller set a + * different mode and then the second overriding the HSM clock + * frequency in its bind. -+ */ + */ +- ret = clk_set_min_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ); + ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ); -+ if (ret) -+ goto err_put_ddc; + if (ret) + goto err_put_ddc; + +- if (vc4_hdmi->variant->reset) +- vc4_hdmi->variant->reset(vc4_hdmi); ++ pm_runtime_enable(dev); + -+ /* -+ * We need to have the device powered up at this point to call -+ * our reset hook and for the CEC init. -+ */ -+ ret = vc4_hdmi_runtime_resume(dev); ++ ret = pm_runtime_resume_and_get(dev); + if (ret) + goto err_put_ddc; -+ -+ pm_runtime_get_noresume(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ - if (vc4_hdmi->variant->reset) - vc4_hdmi->variant->reset(vc4_hdmi); -@@ -1817,8 +2372,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || + of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && +@@ -1827,8 +3278,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); } @@ -60947,7 +64883,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); -@@ -1826,10 +2379,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) +@@ -1836,10 +3285,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_destroy_encoder; @@ -60963,7 +64899,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 ret = vc4_hdmi_audio_init(vc4_hdmi); if (ret) goto err_free_cec; -@@ -1838,14 +2395,19 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) +@@ -1848,14 +3301,19 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi_debugfs_regs, vc4_hdmi); @@ -60983,7 +64919,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 pm_runtime_disable(dev); err_put_ddc: put_device(&vc4_hdmi->ddc->dev); -@@ -1883,6 +2445,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, +@@ -1893,6 +3351,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, kfree(vc4_hdmi->hd_regset.regs); vc4_hdmi_cec_exit(vc4_hdmi); @@ -60991,7 +64927,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 vc4_hdmi_connector_destroy(&vc4_hdmi->connector); drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); -@@ -1912,7 +2475,6 @@ static const struct vc4_hdmi_variant bcm2835_variant = { +@@ -1922,7 +3381,6 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .debugfs_name = "hdmi_regs", .card_name = "vc4-hdmi", .max_pixel_clock = 162000000, @@ -60999,7 +64935,7 @@ index ee293f061f0a..f1adaa9dc5f3 100644 .registers = vc4_hdmi_fields, .num_registers = ARRAY_SIZE(vc4_hdmi_fields), -@@ -1924,14 +2486,16 @@ static const struct vc4_hdmi_variant bcm2835_variant = { +@@ -1934,14 +3392,16 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .phy_disable = vc4_hdmi_phy_disable, .phy_rng_enable = vc4_hdmi_phy_rng_enable, .phy_rng_disable = vc4_hdmi_phy_rng_disable, @@ -61012,12 +64948,12 @@ index ee293f061f0a..f1adaa9dc5f3 100644 .encoder_type = VC4_ENCODER_TYPE_HDMI0, .debugfs_name = "hdmi0_regs", .card_name = "vc4-hdmi-0", -- .max_pixel_clock = 297000000, +- .max_pixel_clock = HDMI_14_MAX_TMDS_CLK, + .max_pixel_clock = 600000000, .registers = vc5_hdmi_hdmi0_fields, .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields), .phy_lane_mapping = { -@@ -1941,6 +2505,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { +@@ -1951,6 +3411,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { PHY_LANE_CK, }, .unsupported_odd_h_timings = true, @@ -61025,25 +64961,18 @@ index ee293f061f0a..f1adaa9dc5f3 100644 .init_resources = vc5_hdmi_init_resources, .csc_setup = vc5_hdmi_csc_setup, -@@ -1950,14 +2515,16 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { +@@ -1960,7 +3421,10 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { .phy_disable = vc5_hdmi_phy_disable, .phy_rng_enable = vc5_hdmi_phy_rng_enable, .phy_rng_disable = vc5_hdmi_phy_rng_disable, + .calc_hsm_clock = vc5_hdmi_calc_hsm_clock, .channel_map = vc5_hdmi_channel_map, + .supports_hdr = true, ++ .hp_detect = vc5_hdmi_hp_detect, }; static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { - .encoder_type = VC4_ENCODER_TYPE_HDMI1, - .debugfs_name = "hdmi1_regs", - .card_name = "vc4-hdmi-1", -- .max_pixel_clock = 297000000, -+ .max_pixel_clock = HDMI_14_MAX_TMDS_CLK, - .registers = vc5_hdmi_hdmi1_fields, - .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi1_fields), - .phy_lane_mapping = { -@@ -1967,6 +2534,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { +@@ -1977,6 +3441,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { PHY_LANE_2, }, .unsupported_odd_h_timings = true, @@ -61051,21 +64980,30 @@ index ee293f061f0a..f1adaa9dc5f3 100644 .init_resources = vc5_hdmi_init_resources, .csc_setup = vc5_hdmi_csc_setup, -@@ -1976,7 +2544,9 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { +@@ -1986,7 +3451,10 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { .phy_disable = vc5_hdmi_phy_disable, .phy_rng_enable = vc5_hdmi_phy_rng_enable, .phy_rng_disable = vc5_hdmi_phy_rng_disable, + .calc_hsm_clock = vc5_hdmi_calc_hsm_clock, .channel_map = vc5_hdmi_channel_map, + .supports_hdr = true, ++ .hp_detect = vc5_hdmi_hp_detect, }; static const struct of_device_id vc4_hdmi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index 0526a9cf608a..49fc91962fe4 100644 +index 0526a9cf608a..fa57d853b100 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -21,10 +21,9 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) +@@ -12,7 +12,6 @@ + struct vc4_hdmi_encoder { + struct vc4_encoder base; + bool hdmi_monitor; +- bool limited_rgb_range; + }; + + static inline struct vc4_hdmi_encoder * +@@ -21,10 +20,9 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_hdmi_encoder, base.base); } @@ -61077,7 +65015,7 @@ index 0526a9cf608a..49fc91962fe4 100644 enum vc4_hdmi_phy_channel { PHY_LANE_0 = 0, -@@ -43,9 +42,6 @@ struct vc4_hdmi_variant { +@@ -43,9 +41,6 @@ struct vc4_hdmi_variant { /* Filename to expose the registers in debugfs */ const char *debugfs_name; @@ -61087,7 +65025,7 @@ index 0526a9cf608a..49fc91962fe4 100644 /* Maximum pixel clock supported by the controller (in Hz) */ unsigned long long max_pixel_clock; -@@ -65,6 +61,13 @@ struct vc4_hdmi_variant { +@@ -65,6 +60,13 @@ struct vc4_hdmi_variant { /* The BCM2711 cannot deal with odd horizontal pixel timings */ bool unsupported_odd_h_timings; @@ -61101,7 +65039,14 @@ index 0526a9cf608a..49fc91962fe4 100644 /* Callback to get the resources (memory region, interrupts, * clocks, etc) for that variant. */ -@@ -78,11 +81,12 @@ struct vc4_hdmi_variant { +@@ -74,15 +76,18 @@ struct vc4_hdmi_variant { + void (*reset)(struct vc4_hdmi *vc4_hdmi); + + /* Callback to enable / disable the CSC */ +- void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable); ++ void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, ++ struct drm_connector_state *state, ++ const struct drm_display_mode *mode); /* Callback to configure the video timings in the HDMI block */ void (*set_timings)(struct vc4_hdmi *vc4_hdmi, @@ -61116,7 +65061,7 @@ index 0526a9cf608a..49fc91962fe4 100644 /* Callback to disable the PHY */ void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); -@@ -93,8 +97,14 @@ struct vc4_hdmi_variant { +@@ -93,8 +98,17 @@ struct vc4_hdmi_variant { /* Callback to disable the RNG in the PHY */ void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi); @@ -61128,10 +65073,13 @@ index 0526a9cf608a..49fc91962fe4 100644 + + /* Enables HDR metadata */ + bool supports_hdr; ++ ++ /* Callback for hardware specific hotplug detect */ ++ bool (*hp_detect)(struct vc4_hdmi *vc4_hdmi); }; /* HDMI audio information */ -@@ -104,11 +114,8 @@ struct vc4_hdmi_audio { +@@ -104,14 +118,18 @@ struct vc4_hdmi_audio { struct snd_soc_dai_link_component cpu; struct snd_soc_dai_link_component codec; struct snd_soc_dai_link_component platform; @@ -61144,16 +65092,28 @@ index 0526a9cf608a..49fc91962fe4 100644 bool streaming; }; -@@ -122,6 +129,8 @@ struct vc4_hdmi { ++enum vc4_hdmi_output_format { ++ VC4_HDMI_OUTPUT_RGB, ++ VC4_HDMI_OUTPUT_YUV422, ++ VC4_HDMI_OUTPUT_YUV444, ++ VC4_HDMI_OUTPUT_YUV420, ++}; ++ + /* General HDMI hardware state. */ + struct vc4_hdmi { + struct vc4_hdmi_audio audio; +@@ -122,6 +140,10 @@ struct vc4_hdmi { struct vc4_hdmi_encoder encoder; struct drm_connector connector; + struct delayed_work scrambling_work; ++ ++ struct drm_property *broadcast_rgb_property; + struct i2c_adapter *ddc; void __iomem *hdmicore_regs; void __iomem *hd_regs; -@@ -150,11 +159,20 @@ struct vc4_hdmi { +@@ -150,11 +172,20 @@ struct vc4_hdmi { */ bool disable_wifi_frequencies; @@ -61174,7 +65134,7 @@ index 0526a9cf608a..49fc91962fe4 100644 struct clk *pixel_clock; struct clk *hsm_clock; struct clk *audio_clock; -@@ -162,8 +180,19 @@ struct vc4_hdmi { +@@ -162,8 +193,75 @@ struct vc4_hdmi { struct reset_control *reset; @@ -61184,6 +65144,7 @@ index 0526a9cf608a..49fc91962fe4 100644 + /* Common debugfs regset */ struct debugfs_regset32 hdmi_regset; struct debugfs_regset32 hd_regset; ++ + /* VC5 debugfs regset */ + struct debugfs_regset32 cec_regset; + struct debugfs_regset32 csc_regset; @@ -61191,16 +65152,74 @@ index 0526a9cf608a..49fc91962fe4 100644 + struct debugfs_regset32 phy_regset; + struct debugfs_regset32 ram_regset; + struct debugfs_regset32 rm_regset; ++ ++ /** ++ * @hw_lock: Spinlock protecting device register access. ++ */ ++ spinlock_t hw_lock; ++ ++ /** ++ * @mutex: Mutex protecting the driver access across multiple ++ * frameworks (KMS, ALSA). ++ * ++ * NOTE: While supported, CEC has been left out since ++ * cec_s_phys_addr_from_edid() might call .adap_enable and lead to a ++ * reentrancy issue between .get_modes (or .detect) and .adap_enable. ++ * Since we don't share any state between the CEC hooks and KMS', it's ++ * not a big deal. The only trouble might come from updating the CEC ++ * clock divider which might be affected by a modeset, but CEC should ++ * be resilient to that. ++ */ ++ struct mutex mutex; ++ ++ /** ++ * @saved_adjusted_mode: Copy of @drm_crtc_state.adjusted_mode ++ * for use by ALSA hooks and interrupt handlers. Protected by @mutex. ++ */ ++ struct drm_display_mode saved_adjusted_mode; ++ ++ /** ++ * @output_enabled: Is the HDMI controller currently active? ++ * Protected by @mutex. ++ */ ++ bool output_enabled; ++ ++ /** ++ * @scdc_enabled: Is the HDMI controller currently running with ++ * the scrambler on? Protected by @mutex. ++ */ ++ bool scdc_enabled; ++ ++ /** ++ * @output_bpc: Copy of @vc4_connector_state.output_bpc for use ++ * outside of KMS hooks. Protected by @mutex. ++ */ ++ unsigned int output_bpc; ++ ++ /** ++ * @output_format: Copy of @vc4_connector_state.output_format ++ * for use outside of KMS hooks. Protected by @mutex. ++ */ ++ enum vc4_hdmi_output_format output_format; ++ ++ /** ++ * @broadcast_rgb: Copy of @vc4_connector_state.broadcast_rgb ++ * for use outside of KMS hooks. Protected by @mutex. ++ */ ++ int broadcast_rgb; }; static inline struct vc4_hdmi * -@@ -180,14 +209,25 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) +@@ -180,14 +278,34 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) return container_of(_encoder, struct vc4_hdmi, encoder); } +struct vc4_hdmi_connector_state { + struct drm_connector_state base; + unsigned long long pixel_rate; ++ unsigned int output_bpc; ++ enum vc4_hdmi_output_format output_format; ++ int broadcast_rgb; +}; + +static inline struct vc4_hdmi_connector_state * @@ -61208,6 +65227,12 @@ index 0526a9cf608a..49fc91962fe4 100644 +{ + return container_of(conn_state, struct vc4_hdmi_connector_state, base); +} ++ ++static inline const struct vc4_hdmi_connector_state * ++const_conn_state_to_vc4_hdmi_conn_state(const struct drm_connector_state *conn_state) ++{ ++ return container_of(conn_state, struct vc4_hdmi_connector_state, base); ++} + void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct drm_display_mode *mode); @@ -61223,10 +65248,10 @@ index 0526a9cf608a..49fc91962fe4 100644 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c -index 057796b54c51..36535480f8e2 100644 +index 057796b54c51..62148f0dc284 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c -@@ -127,7 +127,8 @@ +@@ -127,33 +127,52 @@ #define OSCILLATOR_FREQUENCY 54000000 @@ -61234,9 +65259,59 @@ index 057796b54c51..36535480f8e2 100644 +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, + struct vc4_hdmi_connector_state *conn_state) { ++ unsigned long flags; ++ /* PHY should be in reset, like * vc4_hdmi_encoder_disable() does. -@@ -339,11 +340,12 @@ static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) + */ + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + HDMI_READ(HDMI_TX_PHY_CTL_0) & + ~VC4_HDMI_TX_PHY_RNG_PWRDN); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + HDMI_READ(HDMI_TX_PHY_CTL_0) | + VC4_HDMI_TX_PHY_RNG_PWRDN); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + static unsigned long long +@@ -335,21 +354,27 @@ phy_get_channel_settings(enum vc4_hdmi_phy_channel chan, + + static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) + { ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f); HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10)); } @@ -61250,9 +65325,56 @@ index 057796b54c51..36535480f8e2 100644 + unsigned long long pixel_freq = conn_state->pixel_rate; unsigned long long vco_freq; unsigned char word_sel; ++ unsigned long flags; u8 vco_sel, vco_div; + + vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div); + ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ + vc5_hdmi_reset_phy(vc4_hdmi); + + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, +@@ -499,23 +524,37 @@ void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) + HDMI_READ(HDMI_TX_PHY_RESET_CTL) | + VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB | + VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + vc5_hdmi_reset_phy(vc4_hdmi); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, + HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) & + ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, + HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) | + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -index 6c0dfbbe1a7e..23930a8fa376 100644 +index 6c0dfbbe1a7e..0198de96c7b2 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -1,6 +1,8 @@ @@ -61264,7 +65386,15 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 #include "vc4_hdmi.h" #define VC4_HDMI_PACKET_STRIDE 0x24 -@@ -60,9 +62,12 @@ enum vc4_hdmi_field { +@@ -52,6 +54,7 @@ enum vc4_hdmi_field { + HDMI_CSC_24_23, + HDMI_CSC_32_31, + HDMI_CSC_34_33, ++ HDMI_CSC_CHANNEL_CTL, + HDMI_CSC_CTL, + + /* +@@ -60,9 +63,12 @@ enum vc4_hdmi_field { */ HDMI_CTS_0, HDMI_CTS_1, @@ -61277,7 +65407,7 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 HDMI_HORZA, HDMI_HORZB, HDMI_HOTPLUG, -@@ -97,6 +102,7 @@ enum vc4_hdmi_field { +@@ -97,6 +103,7 @@ enum vc4_hdmi_field { HDMI_RM_FORMAT, HDMI_RM_OFFSET, HDMI_SCHEDULER_CONTROL, @@ -61285,7 +65415,14 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 HDMI_SW_RESET_CONTROL, HDMI_TX_PHY_CHANNEL_SWAP, HDMI_TX_PHY_CLK_DIV, -@@ -119,6 +125,7 @@ enum vc4_hdmi_field { +@@ -113,12 +120,14 @@ enum vc4_hdmi_field { + HDMI_TX_PHY_POWERDOWN_CTL, + HDMI_TX_PHY_RESET_CTL, + HDMI_TX_PHY_TMDS_CLK_WORD_SEL, ++ HDMI_VEC_INTERFACE_CFG, + HDMI_VEC_INTERFACE_XBAR, + HDMI_VERTA0, + HDMI_VERTA1, HDMI_VERTB0, HDMI_VERTB1, HDMI_VID_CTL, @@ -61293,7 +65430,7 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 }; struct vc4_hdmi_register { -@@ -143,7 +150,7 @@ struct vc4_hdmi_register { +@@ -143,7 +152,7 @@ struct vc4_hdmi_register { #define VC5_RAM_REG(reg, offset) _VC4_REG(VC5_RAM, reg, offset) #define VC5_RM_REG(reg, offset) _VC4_REG(VC5_RM, reg, offset) @@ -61302,7 +65439,7 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 VC4_HD_REG(HDMI_M_CTL, 0x000c), VC4_HD_REG(HDMI_MAI_CTL, 0x0014), VC4_HD_REG(HDMI_MAI_THR, 0x0018), -@@ -205,7 +212,7 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = { +@@ -205,7 +214,7 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = { VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400), }; @@ -61311,7 +65448,7 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 VC4_HD_REG(HDMI_DVP_CTL, 0x0000), VC4_HD_REG(HDMI_MAI_CTL, 0x0010), VC4_HD_REG(HDMI_MAI_THR, 0x0014), -@@ -229,9 +236,14 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = { +@@ -229,11 +238,17 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = { VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), @@ -61325,9 +65462,15 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 + VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec), VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), -@@ -281,7 +293,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = { + + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), +@@ -279,9 +294,10 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = { + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), }; -static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = { @@ -61335,7 +65478,7 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 VC4_HD_REG(HDMI_DVP_CTL, 0x0000), VC4_HD_REG(HDMI_MAI_CTL, 0x0030), VC4_HD_REG(HDMI_MAI_THR, 0x0034), -@@ -305,9 +317,14 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = { +@@ -305,11 +321,17 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = { VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), @@ -61349,30 +65492,43 @@ index 6c0dfbbe1a7e..23930a8fa376 100644 + VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec), VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), -@@ -400,6 +417,8 @@ static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, + + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), +@@ -355,6 +377,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = { + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), + }; + + static inline +@@ -400,6 +423,8 @@ static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, const struct vc4_hdmi_variant *variant = hdmi->variant; void __iomem *base; -+ WARN_ON(!pm_runtime_active(&hdmi->pdev->dev)); ++ WARN_ON(pm_runtime_status_suspended(&hdmi->pdev->dev)); + if (reg >= variant->num_registers) { dev_warn(&hdmi->pdev->dev, "Invalid register ID %u\n", reg); -@@ -426,6 +445,8 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, +@@ -426,6 +451,10 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, const struct vc4_hdmi_variant *variant = hdmi->variant; void __iomem *base; -+ WARN_ON(!pm_runtime_active(&hdmi->pdev->dev)); ++ lockdep_assert_held(&hdmi->hw_lock); ++ ++ WARN_ON(pm_runtime_status_suspended(&hdmi->pdev->dev)); + if (reg >= variant->num_registers) { dev_warn(&hdmi->pdev->dev, "Invalid register ID %u\n", reg); diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index ad691571d759..6049923422d0 100644 +index 95fa6fc052a7..fc4de2f6e922 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -95,6 +95,45 @@ static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data) +@@ -95,6 +95,123 @@ static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data) return 0; } @@ -61414,25 +65570,248 @@ index ad691571d759..6049923422d0 100644 + + return 0; +} ++ ++static int vc5_hvs_debugfs_gamma(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct drm_printer p = drm_seq_file_printer(m); ++ unsigned int i, chan; ++ u32 dispstat, dispbkgndx; ++ ++ for (chan = 0; chan < SCALER_CHANNELS_COUNT; chan++) { ++ u32 x_c, grad; ++ u32 offset = SCALER5_DSPGAMMA_START + ++ chan * SCALER5_DSPGAMMA_CHAN_OFFSET; ++ ++ dispstat = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)), ++ SCALER_DISPSTATX_MODE); ++ if (dispstat == SCALER_DISPSTATX_MODE_DISABLED || ++ dispstat == SCALER_DISPSTATX_MODE_EOF) { ++ drm_printf(&p, "HVS channel %u: Channel disabled\n", chan); ++ continue; ++ } ++ ++ dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan)); ++ if (!(dispbkgndx & SCALER_DISPBKGND_GAMMA)) { ++ drm_printf(&p, "HVS channel %u: Gamma disabled\n", chan); ++ continue; ++ } ++ ++ drm_printf(&p, "HVS channel %u:\n", chan); ++ drm_printf(&p, " red:\n"); ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { ++ x_c = HVS_READ(offset); ++ grad = HVS_READ(offset + 4); ++ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", ++ x_c, grad, ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), ++ grad); ++ } ++ drm_printf(&p, " green:\n"); ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { ++ x_c = HVS_READ(offset); ++ grad = HVS_READ(offset + 4); ++ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", ++ x_c, grad, ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), ++ grad); ++ } ++ drm_printf(&p, " blue:\n"); ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { ++ x_c = HVS_READ(offset); ++ grad = HVS_READ(offset + 4); ++ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", ++ x_c, grad, ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), ++ grad); ++ } ++ ++ /* Alpha only valid on channel 2 */ ++ if (chan != 2) ++ continue; ++ ++ drm_printf(&p, " alpha:\n"); ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { ++ x_c = HVS_READ(offset); ++ grad = HVS_READ(offset + 4); ++ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", ++ x_c, grad, ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), ++ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), ++ grad); ++ } ++ } ++ return 0; ++} + /* The filter kernel is composed of dwords each containing 3 9-bit * signed integers packed next to each other. */ -@@ -326,10 +365,10 @@ void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan) +@@ -197,6 +314,80 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc) + vc4_hvs_lut_load(crtc); + } + ++static void vc5_hvs_write_gamma_entry(struct vc4_dev *vc4, ++ u32 offset, ++ struct vc5_gamma_entry *gamma) ++{ ++ HVS_WRITE(offset, gamma->x_c_terms); ++ HVS_WRITE(offset + 4, gamma->grad_term); ++} ++ ++static void vc5_hvs_lut_load(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); ++ u32 i; ++ u32 offset = SCALER5_DSPGAMMA_START + ++ vc4_state->assigned_channel * SCALER5_DSPGAMMA_CHAN_OFFSET; ++ ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) ++ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_r[i]); ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) ++ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_g[i]); ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) ++ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_b[i]); ++ ++ if (vc4_state->assigned_channel == 2) { ++ /* Alpha only valid on channel 2 */ ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) ++ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_a[i]); ++ } ++} ++ ++static void vc5_hvs_update_gamma_lut(struct drm_crtc *crtc) ++{ ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ struct drm_color_lut *lut = crtc->state->gamma_lut->data; ++ unsigned int step, i; ++ u32 start, end; ++ ++#define VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl, chan) \ ++ start = drm_color_lut_extract(lut[i * step].chan, 12); \ ++ end = drm_color_lut_extract(lut[(i + 1) * step - 1].chan, 12); \ ++ \ ++ /* Negative gradients not permitted by the hardware, so \ ++ * flatten such points out. \ ++ */ \ ++ if (end < start) \ ++ end = start; \ ++ \ ++ /* Assume 12bit pipeline. \ ++ * X evenly spread over full range (12 bit). \ ++ * C as U12.4 format. \ ++ * Gradient as U4.8 format. \ ++ */ \ ++ vc4_crtc->pwl[i] = \ ++ VC5_HVS_SET_GAMMA_ENTRY(i << 8, start << 4, \ ++ ((end - start) << 4) / (step - 1)) ++ ++ /* HVS5 has a 16 point piecewise linear function for each colour ++ * channel (including alpha on channel 2) on each display channel. ++ * ++ * Currently take a crude subsample of the gamma LUT, but this could ++ * be improved to implement curve fitting. ++ */ ++ step = crtc->gamma_size / SCALER5_DSPGAMMA_NUM_POINTS; ++ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++) { ++ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_r, red); ++ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_g, green); ++ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_b, blue); ++ } ++ ++ vc5_hvs_lut_load(crtc); ++} ++ + int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); +@@ -289,15 +480,21 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, + dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; + dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE; + ++ if (crtc->state->gamma_lut) ++ /* Enable gamma on if required */ ++ dispbkgndx |= SCALER_DISPBKGND_GAMMA; ++ + HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx | + SCALER_DISPBKGND_AUTOHS | +- ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) | + (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); + + /* Reload the LUT, since the SRAMs would have been disabled if + * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once. + */ +- vc4_hvs_lut_load(crtc); ++ if (!vc4->hvs->hvs5) ++ vc4_hvs_lut_load(crtc); ++ else ++ vc5_hvs_lut_load(crtc); + + return 0; + } +@@ -326,10 +523,50 @@ void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan) SCALER_DISPSTATX_EMPTY); } -int vc4_hvs_atomic_check(struct drm_crtc *crtc, - struct drm_crtc_state *state) -+int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) ++static int vc4_hvs_gamma_check(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) { - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); ++ struct drm_connector_state *conn_state; ++ struct drm_connector *connector; ++ struct drm_device *dev = crtc->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ if (!vc4->hvs->hvs5) ++ return 0; ++ ++ if (!crtc_state->color_mgmt_changed) ++ return 0; ++ ++ if (crtc_state->gamma_lut) { ++ unsigned int len = drm_color_lut_size(crtc_state->gamma_lut); ++ ++ if (len != crtc->gamma_size) { ++ DRM_DEBUG_KMS("Invalid LUT size; got %u, expected %u\n", ++ len, crtc->gamma_size); ++ return -EINVAL; ++ } ++ } ++ ++ connector = vc4_get_crtc_connector(crtc, crtc_state); ++ if (!connector) ++ return -EINVAL; ++ ++ if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)) ++ return 0; ++ ++ conn_state = drm_atomic_get_connector_state(state, connector); ++ if (!conn_state) ++ return -EINVAL; ++ ++ crtc_state->mode_changed = true; ++ return 0; ++} ++ ++int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) ++{ ++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct drm_plane *plane; -@@ -341,10 +380,10 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, +@@ -341,10 +578,10 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, /* The pixelvalve can only feed one encoder (and encoders are * 1:1 with connectors.) */ @@ -61445,7 +65824,55 @@ index ad691571d759..6049923422d0 100644 dlist_count += vc4_plane_dlist_size(plane_state); dlist_count++; /* Account for SCALER_CTL0_END. */ -@@ -391,11 +430,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) +@@ -356,7 +593,7 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, + if (ret) + return ret; + +- return 0; ++ return vc4_hvs_gamma_check(crtc, state); + } + + static void vc4_hvs_update_dlist(struct drm_crtc *crtc) +@@ -365,17 +602,16 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); ++ unsigned long flags; + + 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); + +- if (!vc4_state->feed_txp || vc4_state->txp_armed) { ++ if (!vc4_crtc->feeds_txp || vc4_state->txp_armed) { + vc4_crtc->event = crtc->state->event; + crtc->state->event = NULL; + } +@@ -388,25 +624,42 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) + HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), + vc4_state->mm.start); + } ++ ++ spin_lock_irqsave(&vc4_crtc->irq_lock, flags); ++ vc4_crtc->current_dlist = vc4_state->mm.start; ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); ++} ++ ++void vc4_hvs_atomic_begin(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_crtc->irq_lock, flags); ++ vc4_crtc->current_hvs_channel = vc4_state->assigned_channel; ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); } void vc4_hvs_atomic_enable(struct drm_crtc *crtc, @@ -61455,12 +65882,13 @@ index ad691571d759..6049923422d0 100644 struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); -+ struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); -+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(new_crtc_state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; - bool oneshot = vc4_state->feed_txp; +- bool oneshot = vc4_state->feed_txp; ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ bool oneshot = vc4_crtc->feeds_txp; -@@ -404,9 +444,10 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, + vc4_hvs_update_dlist(crtc); + vc4_hvs_init_channel(vc4, crtc, mode, oneshot); } void vc4_hvs_atomic_disable(struct drm_crtc *crtc, @@ -61472,7 +65900,7 @@ index ad691571d759..6049923422d0 100644 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state); unsigned int chan = vc4_state->assigned_channel; -@@ -414,8 +455,10 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc, +@@ -414,8 +667,10 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc, } void vc4_hvs_atomic_flush(struct drm_crtc *crtc, @@ -61484,17 +65912,49 @@ index ad691571d759..6049923422d0 100644 struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); -@@ -671,6 +714,8 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) +@@ -477,14 +732,25 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, + u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)); + + if (crtc->state->gamma_lut) { +- vc4_hvs_update_gamma_lut(crtc); +- dispbkgndx |= SCALER_DISPBKGND_GAMMA; ++ if (!vc4->hvs->hvs5) { ++ vc4_hvs_update_gamma_lut(crtc); ++ dispbkgndx |= SCALER_DISPBKGND_GAMMA; ++ } else { ++ vc5_hvs_update_gamma_lut(crtc); ++ } + } else { + /* Unsetting DISPBKGND_GAMMA skips the gamma lut step + * in hardware, which is the same as a linear lut that + * DRM expects us to use in absence of a user lut. ++ * ++ * Do NOT change state dynamically for hvs5 as it ++ * inserts a delay in the pipeline that will cause ++ * stalls if enabled/disabled whilst running. The other ++ * should already be disabling/enabling the pipeline ++ * when gamma changes. + */ +- dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; ++ if (!vc4->hvs->hvs5) ++ dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; + } + HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx); + } +@@ -687,6 +953,11 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset); vc4_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun, NULL); + vc4_debugfs_add_file(drm, "hvs_dlists", vc4_hvs_debugfs_dlist, + NULL); ++ if (hvs->hvs5) ++ vc4_debugfs_add_file(drm, "hvs_gamma", vc5_hvs_debugfs_gamma, ++ NULL); return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index ba310c0ab5f6..fb2465964d46 100644 +index ba310c0ab5f6..422f2c211abd 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -40,6 +40,9 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv) @@ -61537,7 +65997,24 @@ index ba310c0ab5f6..fb2465964d46 100644 static struct vc4_hvs_state * vc4_hvs_get_global_state(struct drm_atomic_state *state) { -@@ -309,21 +328,44 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) +@@ -203,6 +222,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, + unsigned int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + u32 dispctrl; + u32 dsp3_mux; +@@ -223,7 +243,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, + * TXP IP, and we need to disable the FIFO2 -> pixelvalve1 + * route. + */ +- if (vc4_state->feed_txp) ++ if (vc4_crtc->feeds_txp) + dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX); + else + dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); +@@ -309,21 +329,44 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_hvs *hvs = vc4->hvs; struct drm_crtc_state *new_crtc_state; @@ -61585,7 +66062,7 @@ index ba310c0ab5f6..fb2465964d46 100644 drm_atomic_helper_wait_for_fences(dev, state, false); -@@ -333,10 +375,12 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) +@@ -333,10 +376,12 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) vc4_ctm_commit(vc4, state); @@ -61602,7 +66079,7 @@ index ba310c0ab5f6..fb2465964d46 100644 drm_atomic_helper_commit_planes(dev, state, 0); -@@ -352,8 +396,20 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) +@@ -352,8 +397,20 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) drm_atomic_helper_commit_cleanup_done(state); @@ -61625,7 +66102,7 @@ index ba310c0ab5f6..fb2465964d46 100644 drm_atomic_state_put(state); -@@ -413,7 +469,8 @@ static int vc4_atomic_commit(struct drm_device *dev, +@@ -413,7 +470,8 @@ static int vc4_atomic_commit(struct drm_device *dev, * drm_atomic_helper_setup_commit() from auto-completing * commit->flip_done. */ @@ -61635,7 +66112,7 @@ index ba310c0ab5f6..fb2465964d46 100644 ret = drm_atomic_helper_setup_commit(state, nonblock); if (ret) return ret; -@@ -591,9 +648,6 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state) +@@ -591,9 +649,6 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state) struct drm_plane *plane; int i; @@ -61645,7 +66122,7 @@ index ba310c0ab5f6..fb2465964d46 100644 priv_state = drm_atomic_get_private_obj_state(state, &vc4->load_tracker); if (IS_ERR(priv_state)) -@@ -668,9 +722,6 @@ static void vc4_load_tracker_obj_fini(struct drm_device *dev, void *unused) +@@ -668,9 +723,6 @@ static void vc4_load_tracker_obj_fini(struct drm_device *dev, void *unused) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -61655,7 +66132,7 @@ index ba310c0ab5f6..fb2465964d46 100644 drm_atomic_private_obj_fini(&vc4->load_tracker); } -@@ -678,9 +729,6 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) +@@ -678,9 +730,6 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) { struct vc4_load_tracker_state *load_state; @@ -61665,7 +66142,7 @@ index ba310c0ab5f6..fb2465964d46 100644 load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); if (!load_state) return -ENOMEM; -@@ -705,6 +753,9 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) +@@ -705,6 +754,9 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); state->unassigned_channels = old_state->unassigned_channels; @@ -61675,7 +66152,7 @@ index ba310c0ab5f6..fb2465964d46 100644 return &state->base; } -@@ -778,6 +829,7 @@ static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) +@@ -778,6 +830,7 @@ static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) static int vc4_pv_muxing_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -61683,7 +66160,7 @@ index ba310c0ab5f6..fb2465964d46 100644 struct vc4_hvs_state *hvs_new_state; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; -@@ -794,6 +846,10 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, +@@ -794,6 +847,10 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, to_vc4_crtc_state(new_crtc_state); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); unsigned int matching_channels; @@ -61694,7 +66171,7 @@ index ba310c0ab5f6..fb2465964d46 100644 /* Nothing to do here, let's skip it */ if (old_crtc_state->enable == new_crtc_state->enable) -@@ -834,19 +890,76 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, +@@ -834,19 +891,76 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, * but it works so far. */ matching_channels = hvs_new_state->unassigned_channels & vc4_crtc->data->hvs_available_channels; @@ -61777,7 +66254,7 @@ index ba310c0ab5f6..fb2465964d46 100644 static int vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { -@@ -864,7 +977,11 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) +@@ -864,7 +978,11 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) if (ret) return ret; @@ -61790,7 +66267,7 @@ index ba310c0ab5f6..fb2465964d46 100644 } static const struct drm_mode_config_funcs vc4_mode_funcs = { -@@ -880,9 +997,12 @@ int vc4_kms_load(struct drm_device *dev) +@@ -880,9 +998,12 @@ int vc4_kms_load(struct drm_device *dev) "brcm,bcm2711-vc5"); int ret; @@ -61805,7 +66282,7 @@ index ba310c0ab5f6..fb2465964d46 100644 /* Start with the load tracker enabled. Can be * disabled through the debugfs load_tracker file. */ -@@ -913,6 +1033,8 @@ int vc4_kms_load(struct drm_device *dev) +@@ -913,6 +1034,8 @@ int vc4_kms_load(struct drm_device *dev) dev->mode_config.preferred_depth = 24; dev->mode_config.async_page_flip = true; dev->mode_config.allow_fb_modifiers = true; @@ -61828,7 +66305,7 @@ index f4aa75efd16b..18abc06335c1 100644 static int vc4_perfmon_idr_del(int id, void *elem, void *data) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index af4b8944a603..7947cf47b6e1 100644 +index 4df222a83049..766280a844f4 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -33,6 +33,7 @@ static const struct hvs_format { @@ -61839,7 +66316,7 @@ index af4b8944a603..7947cf47b6e1 100644 } hvs_formats[] = { { .drm = DRM_FORMAT_XRGB8888, -@@ -128,6 +129,12 @@ static const struct hvs_format { +@@ -128,6 +129,40 @@ static const struct hvs_format { .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, .pixel_order = HVS_PIXEL_ORDER_XYCRCB, }, @@ -61848,59 +66325,52 @@ index af4b8944a603..7947cf47b6e1 100644 + .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT, + .pixel_order = HVS_PIXEL_ORDER_XYCBCR, + .hvs5_only = true, ++ }, ++ { ++ .drm = DRM_FORMAT_XRGB2101010, ++ .hvs = HVS_PIXEL_FORMAT_RGBA1010102, ++ .pixel_order = HVS_PIXEL_ORDER_ABGR, ++ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, ++ .hvs5_only = true, ++ }, ++ { ++ .drm = DRM_FORMAT_ARGB2101010, ++ .hvs = HVS_PIXEL_FORMAT_RGBA1010102, ++ .pixel_order = HVS_PIXEL_ORDER_ABGR, ++ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, ++ .hvs5_only = true, ++ }, ++ { ++ .drm = DRM_FORMAT_ABGR2101010, ++ .hvs = HVS_PIXEL_FORMAT_RGBA1010102, ++ .pixel_order = HVS_PIXEL_ORDER_ARGB, ++ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, ++ .hvs5_only = true, ++ }, ++ { ++ .drm = DRM_FORMAT_XBGR2101010, ++ .hvs = HVS_PIXEL_FORMAT_RGBA1010102, ++ .pixel_order = HVS_PIXEL_ORDER_ARGB, ++ .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, ++ .hvs5_only = true, + }, }; static const struct hvs_format *vc4_get_hvs_format(u32 drm_format) -@@ -303,16 +310,16 @@ static int vc4_plane_margins_adj(struct drm_plane_state *pstate) - adjhdisplay, - crtc_state->mode.hdisplay); - vc4_pstate->crtc_x += left; -- if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left) -- vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left; -+ if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - right) -+ vc4_pstate->crtc_x = crtc_state->mode.hdisplay - right; - - adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); - vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * - adjvdisplay, - crtc_state->mode.vdisplay); - vc4_pstate->crtc_y += top; -- if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top) -- vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top; -+ if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - bottom) -+ vc4_pstate->crtc_y = crtc_state->mode.vdisplay - bottom; - - vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w * - adjhdisplay, -@@ -332,7 +339,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) - struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); - struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -- u32 subpixel_src_mask = (1 << 16) - 1; - int num_planes = fb->format->num_planes; - struct drm_crtc_state *crtc_state; - u32 h_subsample = fb->format->hsub; -@@ -354,18 +360,14 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) +@@ -353,15 +388,14 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) 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.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.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; +- /* +- * We don't support subpixel source positioning for scaling, + /* We don't support subpixel source positioning for scaling, -+ * but fractional coordinates can be generated by clipping -+ * so just round for now -+ */ + * but fractional coordinates can be generated by clipping + * so just round for now + */ +- vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1 << 16); +- vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1 << 16); +- vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1 << 16) - vc4_state->src_x; +- vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1 << 16) - vc4_state->src_y; + vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1<<16); + vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1<<16); + vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1<<16) - vc4_state->src_x; @@ -61908,7 +66378,7 @@ index af4b8944a603..7947cf47b6e1 100644 vc4_state->crtc_x = state->dst.x1; vc4_state->crtc_y = state->dst.y1; -@@ -532,9 +534,6 @@ static void vc4_plane_calc_load(struct drm_plane_state *state) +@@ -528,9 +562,6 @@ static void vc4_plane_calc_load(struct drm_plane_state *state) struct vc4_dev *vc4; vc4 = to_vc4_dev(state->plane->dev); @@ -61918,7 +66388,7 @@ index af4b8944a603..7947cf47b6e1 100644 vc4_state = to_vc4_plane_state(state); crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); -@@ -621,6 +620,53 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state) +@@ -617,6 +648,95 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state) return 0; } @@ -61968,36 +66438,68 @@ index af4b8944a603..7947cf47b6e1 100644 + } + } +}; ++ ++static u32 vc4_hvs4_get_alpha_blend_mode(struct drm_plane_state *state) ++{ ++ if (!state->fb->format->has_alpha) ++ return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED, ++ SCALER_POS2_ALPHA_MODE); ++ ++ switch (state->pixel_blend_mode) { ++ case DRM_MODE_BLEND_PIXEL_NONE: ++ return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED, ++ SCALER_POS2_ALPHA_MODE); ++ default: ++ case DRM_MODE_BLEND_PREMULTI: ++ return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_PIPELINE, ++ SCALER_POS2_ALPHA_MODE) | ++ SCALER_POS2_ALPHA_PREMULT; ++ case DRM_MODE_BLEND_COVERAGE: ++ return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_PIPELINE, ++ SCALER_POS2_ALPHA_MODE); ++ } ++} ++ ++static u32 vc4_hvs5_get_alpha_blend_mode(struct drm_plane_state *state) ++{ ++ if (!state->fb->format->has_alpha) ++ return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED, ++ SCALER5_CTL2_ALPHA_MODE); ++ ++ switch (state->pixel_blend_mode) { ++ case DRM_MODE_BLEND_PIXEL_NONE: ++ return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED, ++ SCALER5_CTL2_ALPHA_MODE); ++ default: ++ case DRM_MODE_BLEND_PREMULTI: ++ return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_PIPELINE, ++ SCALER5_CTL2_ALPHA_MODE) | ++ SCALER5_CTL2_ALPHA_PREMULT; ++ case DRM_MODE_BLEND_COVERAGE: ++ return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_PIPELINE, ++ SCALER5_CTL2_ALPHA_MODE); ++ } ++} + /* Writes out a full display list for an active plane to the plane's * private dlist state. */ -@@ -769,45 +815,67 @@ static int vc4_plane_mode_set(struct drm_plane *plane, +@@ -763,47 +883,90 @@ static int vc4_plane_mode_set(struct drm_plane *plane, + case DRM_FORMAT_MOD_BROADCOM_SAND128: + case DRM_FORMAT_MOD_BROADCOM_SAND256: { uint32_t param = fourcc_mod_broadcom_param(fb->modifier); - u32 tile_w, tile, x_off, pix_per_tile; - +- u32 tile_w, tile, x_off, pix_per_tile; +- - hvs_format = HVS_PIXEL_FORMAT_H264; -+ if (fb->format->format == DRM_FORMAT_P030) { -+ /* -+ * Spec says: bits [31:4] of the given address should point to -+ * the 128-bit word containing the desired starting pixel, -+ * and bits[3:0] should be between 0 and 11, indicating which -+ * of the 12-pixels in that 128-bit word is the first pixel to be used -+ */ -+ u32 remaining_pixels = vc4_state->src_x % 96; -+ u32 aligned = remaining_pixels / 12; -+ u32 last_bits = remaining_pixels % 12; - +- - switch (base_format_mod) { - case DRM_FORMAT_MOD_BROADCOM_SAND64: - tiling = SCALER_CTL0_TILING_64B; - tile_w = 64; - break; - case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ x_off = aligned * 16 + last_bits; -+ hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; - tiling = SCALER_CTL0_TILING_128B; - tile_w = 128; +- tiling = SCALER_CTL0_TILING_128B; +- tile_w = 128; - break; - case DRM_FORMAT_MOD_BROADCOM_SAND256: - tiling = SCALER_CTL0_TILING_256B_OR_T; @@ -62005,42 +66507,39 @@ index af4b8944a603..7947cf47b6e1 100644 - break; - default: - break; -+ pix_per_tile = 96; +- } + + if (param > SCALER_TILE_HEIGHT_MASK) { +- DRM_DEBUG_KMS("SAND height too large (%d)\n", param); ++ DRM_DEBUG_KMS("SAND height too large (%d)\n", ++ param); + return -EINVAL; + } + +- pix_per_tile = tile_w / fb->format->cpp[0]; +- tile = vc4_state->src_x / pix_per_tile; +- x_off = vc4_state->src_x % pix_per_tile; ++ if (fb->format->format == DRM_FORMAT_P030) { ++ hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; ++ tiling = SCALER_CTL0_TILING_128B; + } else { + hvs_format = HVS_PIXEL_FORMAT_H264; + + switch (base_format_mod) { + case DRM_FORMAT_MOD_BROADCOM_SAND64: + tiling = SCALER_CTL0_TILING_64B; -+ tile_w = 64; + break; + case DRM_FORMAT_MOD_BROADCOM_SAND128: + tiling = SCALER_CTL0_TILING_128B; -+ tile_w = 128; + break; + case DRM_FORMAT_MOD_BROADCOM_SAND256: + tiling = SCALER_CTL0_TILING_256B_OR_T; -+ tile_w = 256; + break; + default: -+ break; ++ return -EINVAL; + } -+ pix_per_tile = tile_w / fb->format->cpp[0]; -+ x_off = (vc4_state->src_x % pix_per_tile) / -+ (i ? h_subsample : 1) * fb->format->cpp[i]; - } -- - if (param > SCALER_TILE_HEIGHT_MASK) { -- DRM_DEBUG_KMS("SAND height too large (%d)\n", param); -+ DRM_DEBUG_KMS("SAND height too large (%d)\n", -+ param); - return -EINVAL; - } -- -- pix_per_tile = tile_w / fb->format->cpp[0]; - tile = vc4_state->src_x / pix_per_tile; -- x_off = vc4_state->src_x % pix_per_tile; -- ++ } + /* Adjust the base pointer to the first pixel to be scanned * out. + * @@ -62052,6 +66551,46 @@ index af4b8944a603..7947cf47b6e1 100644 + * should be 6. */ for (i = 0; i < num_planes; i++) { ++ u32 tile_w, tile, x_off, pix_per_tile; ++ ++ if (fb->format->format == DRM_FORMAT_P030) { ++ /* ++ * Spec says: bits [31:4] of the given address ++ * should point to the 128-bit word containing ++ * the desired starting pixel, and bits[3:0] ++ * should be between 0 and 11, indicating which ++ * of the 12-pixels in that 128-bit word is the ++ * first pixel to be used ++ */ ++ u32 remaining_pixels = vc4_state->src_x % 96; ++ u32 aligned = remaining_pixels / 12; ++ u32 last_bits = remaining_pixels % 12; ++ ++ x_off = aligned * 16 + last_bits; ++ tile_w = 128; ++ pix_per_tile = 96; ++ } else { ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_BROADCOM_SAND64: ++ tile_w = 64; ++ break; ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ tile_w = 128; ++ break; ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: ++ tile_w = 256; ++ break; ++ default: ++ return -EINVAL; ++ } ++ pix_per_tile = tile_w / fb->format->cpp[0]; ++ x_off = (vc4_state->src_x % pix_per_tile) / ++ (i ? h_subsample : 1) * ++ fb->format->cpp[i]; ++ } ++ ++ tile = vc4_state->src_x / pix_per_tile; ++ vc4_state->offsets[i] += param * tile_w * tile; vc4_state->offsets[i] += src_y / (i ? v_subsample : 1) * @@ -62063,7 +66602,39 @@ index af4b8944a603..7947cf47b6e1 100644 } pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); -@@ -960,7 +1028,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, +@@ -856,13 +1019,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, + /* Position Word 2: Source Image Size, Alpha */ + vc4_state->pos2_offset = vc4_state->dlist_count; + vc4_dlist_write(vc4_state, +- VC4_SET_FIELD(fb->format->has_alpha ? +- SCALER_POS2_ALPHA_MODE_PIPELINE : +- SCALER_POS2_ALPHA_MODE_FIXED, +- SCALER_POS2_ALPHA_MODE) | + (mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) | +- (fb->format->has_alpha ? +- SCALER_POS2_ALPHA_PREMULT : 0) | ++ vc4_hvs4_get_alpha_blend_mode(state) | + VC4_SET_FIELD(vc4_state->src_w[0], + SCALER_POS2_WIDTH) | + VC4_SET_FIELD(vc4_state->src_h[0], +@@ -907,14 +1065,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane, + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(state->alpha >> 4, + SCALER5_CTL2_ALPHA) | +- (fb->format->has_alpha ? +- SCALER5_CTL2_ALPHA_PREMULT : 0) | ++ vc4_hvs5_get_alpha_blend_mode(state) | + (mix_plane_alpha ? +- SCALER5_CTL2_ALPHA_MIX : 0) | +- VC4_SET_FIELD(fb->format->has_alpha ? +- SCALER5_CTL2_ALPHA_MODE_PIPELINE : +- SCALER5_CTL2_ALPHA_MODE_FIXED, +- SCALER5_CTL2_ALPHA_MODE) ++ SCALER5_CTL2_ALPHA_MIX : 0) + ); + + /* Position Word 1: Scaled Image Dimensions. */ +@@ -956,7 +1109,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Pitch word 1/2 */ for (i = 1; i < num_planes; i++) { @@ -62073,7 +66644,7 @@ index af4b8944a603..7947cf47b6e1 100644 vc4_dlist_write(vc4_state, VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH)); -@@ -971,9 +1040,20 @@ static int vc4_plane_mode_set(struct drm_plane *plane, +@@ -967,9 +1121,20 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Colorspace conversion words */ if (vc4_state->is_yuv) { @@ -62097,7 +66668,7 @@ index af4b8944a603..7947cf47b6e1 100644 } vc4_state->lbm_offset = 0; -@@ -1146,7 +1226,6 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, +@@ -1142,7 +1307,6 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, plane->state->src_y = state->src_y; plane->state->src_w = state->src_w; plane->state->src_h = state->src_h; @@ -62105,7 +66676,7 @@ index af4b8944a603..7947cf47b6e1 100644 plane->state->alpha = state->alpha; plane->state->pixel_blend_mode = state->pixel_blend_mode; plane->state->rotation = state->rotation; -@@ -1283,11 +1362,6 @@ static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { +@@ -1279,11 +1443,6 @@ static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { .atomic_async_update = vc4_plane_atomic_async_update, }; @@ -62117,7 +66688,7 @@ index af4b8944a603..7947cf47b6e1 100644 static bool vc4_format_mod_supported(struct drm_plane *plane, uint32_t format, uint64_t modifier) -@@ -1320,6 +1394,13 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, +@@ -1316,6 +1475,13 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, default: return false; } @@ -62131,7 +66702,7 @@ index af4b8944a603..7947cf47b6e1 100644 case DRM_FORMAT_RGBX1010102: case DRM_FORMAT_BGRX1010102: case DRM_FORMAT_RGBA1010102: -@@ -1338,7 +1419,7 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, +@@ -1334,7 +1500,7 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, static const struct drm_plane_funcs vc4_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -62140,7 +66711,7 @@ index af4b8944a603..7947cf47b6e1 100644 .set_property = NULL, .reset = vc4_plane_reset, .atomic_duplicate_state = vc4_plane_duplicate_state, -@@ -1352,8 +1433,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, +@@ -1348,8 +1514,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, struct drm_plane *plane = NULL; struct vc4_plane *vc4_plane; u32 formats[ARRAY_SIZE(hvs_formats)]; @@ -62152,7 +66723,7 @@ index af4b8944a603..7947cf47b6e1 100644 static const uint64_t modifiers[] = { DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, DRM_FORMAT_MOD_BROADCOM_SAND128, -@@ -1368,13 +1452,17 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, +@@ -1364,13 +1533,17 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, if (!vc4_plane) return ERR_PTR(-ENOMEM); @@ -62173,7 +66744,17 @@ index af4b8944a603..7947cf47b6e1 100644 modifiers, type, NULL); if (ret) return ERR_PTR(ret); -@@ -1388,6 +1476,15 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, +@@ -1378,12 +1551,25 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, + drm_plane_helper_add(plane, &vc4_plane_helper_funcs); + + drm_plane_create_alpha_property(plane); ++ drm_plane_create_blend_mode_property(plane, ++ BIT(DRM_MODE_BLEND_PIXEL_NONE) | ++ BIT(DRM_MODE_BLEND_PREMULTI) | ++ BIT(DRM_MODE_BLEND_COVERAGE)); + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, + DRM_MODE_ROTATE_0 | + DRM_MODE_ROTATE_180 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y); @@ -62190,10 +66771,39 @@ index af4b8944a603..7947cf47b6e1 100644 } diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index be2c32a519b3..7538b84a6dca 100644 +index be2c32a519b3..f40dd93f2cdd 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -516,6 +516,36 @@ +@@ -491,6 +491,28 @@ + #define SCALER_DLIST_START 0x00002000 + #define SCALER_DLIST_SIZE 0x00004000 + ++/* Gamma PWL for each channel. 16 points for each of 4 colour channels (alpha ++ * only on channel 2). 8 bytes per entry, offsets first, then gradient: ++ * Y = GRAD * X + C ++ * ++ * Values for X and C are left justified, and vary depending on the width of ++ * the HVS channel: ++ * 8-bit pipeline: X uses [31:24], C is U8.8 format, and GRAD is U4.8. ++ * 12-bit pipeline: X uses [31:20], C is U12.4 format, and GRAD is U4.8. ++ * ++ * The 3 HVS channels start at 0x400 offsets (ie chan 1 starts at 0x2400, and ++ * chan 2 at 0x2800). ++ */ ++#define SCALER5_DSPGAMMA_NUM_POINTS 16 ++#define SCALER5_DSPGAMMA_START 0x00002000 ++#define SCALER5_DSPGAMMA_CHAN_OFFSET 0x400 ++# define SCALER5_DSPGAMMA_OFF_X_MASK VC4_MASK(31, 20) ++# define SCALER5_DSPGAMMA_OFF_X_SHIFT 20 ++# define SCALER5_DSPGAMMA_OFF_C_MASK VC4_MASK(15, 0) ++# define SCALER5_DSPGAMMA_OFF_C_SHIFT 0 ++# define SCALER5_DSPGAMMA_GRAD_MASK VC4_MASK(11, 0) ++# define SCALER5_DSPGAMMA_GRAD_SHIFT 0 ++ + #define SCALER5_DLIST_START 0x00004000 + + # define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1) +@@ -516,6 +538,36 @@ # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK VC4_MASK(7, 0) # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT 0 @@ -62230,7 +66840,35 @@ index be2c32a519b3..7538b84a6dca 100644 # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16) /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead -@@ -945,7 +975,10 @@ enum hvs_pixel_format { +@@ -744,8 +796,27 @@ + # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) + # define VC4_HD_CSC_CTL_ENABLE BIT(0) + ++# define VC5_MT_CP_CSC_CTL_USE_444_TO_422 BIT(6) ++# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_MASK \ ++ VC4_MASK(5, 4) ++# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD \ ++ 3 ++# define VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION BIT(3) ++# define VC5_MT_CP_CSC_CTL_ENABLE BIT(2) ++# define VC5_MT_CP_CSC_CTL_MODE_MASK VC4_MASK(1, 0) ++ ++# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_MASK \ ++ VC4_MASK(7, 6) ++# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE \ ++ 2 ++ + # define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1) + ++# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_MASK \ ++ VC4_MASK(3, 2) ++# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY \ ++ 2 ++ + /* HVS display list information. */ + #define HVS_BOOTLOADER_DLIST_END 32 + +@@ -945,7 +1016,10 @@ enum hvs_pixel_format { #define SCALER_CSC0_COEF_CR_OFS_SHIFT 0 #define SCALER_CSC0_ITR_R_601_5 0x00f00000 #define SCALER_CSC0_ITR_R_709_3 0x00f00000 @@ -62241,7 +66879,7 @@ index be2c32a519b3..7538b84a6dca 100644 /* S2.8 contribution of Cb to Green */ #define SCALER_CSC1_COEF_CB_GRN_MASK VC4_MASK(31, 22) -@@ -960,8 +993,11 @@ enum hvs_pixel_format { +@@ -960,8 +1034,11 @@ enum hvs_pixel_format { #define SCALER_CSC1_COEF_CR_BLU_MASK VC4_MASK(1, 0) #define SCALER_CSC1_COEF_CR_BLU_SHIFT 0 #define SCALER_CSC1_ITR_R_601_5 0xe73304a8 @@ -62255,7 +66893,7 @@ index be2c32a519b3..7538b84a6dca 100644 /* S2.8 contribution of Cb to Red */ #define SCALER_CSC2_COEF_CB_RED_MASK VC4_MASK(29, 20) -@@ -972,9 +1008,12 @@ enum hvs_pixel_format { +@@ -972,9 +1049,12 @@ enum hvs_pixel_format { /* S2.8 contribution of Cb to Blue */ #define SCALER_CSC2_COEF_CB_BLU_MASK VC4_MASK(19, 10) #define SCALER_CSC2_COEF_CB_BLU_SHIFT 10 @@ -62272,7 +66910,7 @@ index be2c32a519b3..7538b84a6dca 100644 #define SCALER_TPZ0_VERT_RECALC BIT(31) #define SCALER_TPZ0_SCALE_MASK VC4_MASK(28, 8) diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c -index d13502ae973d..2fc7f4b5fa09 100644 +index f8fa09dfea5d..82beb8c159f2 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -13,6 +13,7 @@ @@ -62295,7 +66933,7 @@ index d13502ae973d..2fc7f4b5fa09 100644 struct vc4_txp *txp = connector_to_vc4_txp(conn); struct drm_gem_cma_object *gem; struct drm_display_mode *mode; -@@ -379,43 +382,44 @@ static const struct drm_crtc_funcs vc4_txp_crtc_funcs = { +@@ -385,43 +388,42 @@ static const struct drm_crtc_funcs vc4_txp_crtc_funcs = { .reset = vc4_crtc_reset, .atomic_duplicate_state = vc4_crtc_duplicate_state, .atomic_destroy_state = vc4_crtc_destroy_state, @@ -62311,7 +66949,6 @@ index d13502ae973d..2fc7f4b5fa09 100644 - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); -+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); int ret; ret = vc4_hvs_atomic_check(crtc, state); @@ -62319,8 +66956,8 @@ index d13502ae973d..2fc7f4b5fa09 100644 return ret; - state->no_vblank = true; +- vc4_state->feed_txp = true; + crtc_state->no_vblank = true; - vc4_state->feed_txp = true; return 0; } @@ -62348,8 +66985,24 @@ index d13502ae973d..2fc7f4b5fa09 100644 /* * Make sure we issue a vblank event after disabling the CRTC if +@@ -439,6 +441,7 @@ static void vc4_txp_atomic_disable(struct drm_crtc *crtc, + + static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = { + .atomic_check = vc4_txp_atomic_check, ++ .atomic_begin = vc4_hvs_atomic_begin, + .atomic_flush = vc4_hvs_atomic_flush, + .atomic_enable = vc4_txp_atomic_enable, + .atomic_disable = vc4_txp_atomic_disable, +@@ -484,6 +487,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) + + vc4_crtc->pdev = pdev; + vc4_crtc->data = &vc4_txp_crtc_data; ++ vc4_crtc->feeds_txp = true; + + txp->pdev = pdev; + diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index bd5b8eb58b18..596b59ff6c9a 100644 +index c6bd168a5898..255e5c6c48e0 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -45,6 +45,7 @@ @@ -62440,7 +67093,7 @@ index bd5b8eb58b18..596b59ff6c9a 100644 struct debugfs_regset32 regset; }; -@@ -206,13 +242,19 @@ to_vc4_vec_connector(struct drm_connector *connector) +@@ -206,13 +242,20 @@ to_vc4_vec_connector(struct drm_connector *connector) enum vc4_vec_tv_mode_id { VC4_VEC_TV_MODE_NTSC, VC4_VEC_TV_MODE_NTSC_J, @@ -62453,15 +67106,17 @@ index bd5b8eb58b18..596b59ff6c9a 100644 }; struct vc4_vec_tv_mode { - const struct drm_display_mode *mode; +- const struct drm_display_mode *mode; - void (*mode_set)(struct vc4_vec *vec); ++ const struct drm_display_mode *interlaced_mode; ++ const struct drm_display_mode *progressive_mode; + u32 config0; + u32 config1; + u32 custom_freq; }; static const struct debugfs_reg32 vec_regs[] = { -@@ -242,66 +284,106 @@ static const struct debugfs_reg32 vec_regs[] = { +@@ -242,66 +285,126 @@ static const struct debugfs_reg32 vec_regs[] = { VC4_REG32(VEC_DAC_MISC), }; @@ -62478,11 +67133,11 @@ index bd5b8eb58b18..596b59ff6c9a 100644 -} - -static const struct drm_display_mode ntsc_mode = { +- DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, +static const struct drm_display_mode drm_mode_480i = { - DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, ++ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, -- 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0, -+ 480, 480 + 7, 480 + 7 + 6, 525, 0, + 480, 480 + 7, 480 + 7 + 6, 525, 0, DRM_MODE_FLAG_INTERLACE) }; @@ -62500,34 +67155,48 @@ index bd5b8eb58b18..596b59ff6c9a 100644 - VEC_WRITE(VEC_FREQ3_2, 0x223b); - VEC_WRITE(VEC_FREQ1_0, 0x61d1); -} -- ++static const struct drm_display_mode drm_mode_240p = { ++ DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, ++ 240, 240 + 3, 240 + 3 + 3, 262, 0, 0) ++}; + -static const struct drm_display_mode pal_mode = { +- DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, +static const struct drm_display_mode drm_mode_576i = { - DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, ++ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, -- 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0, -+ 576, 576 + 4, 576 + 4 + 6, 625, 0, + 576, 576 + 4, 576 + 4 + 6, 625, 0, DRM_MODE_FLAG_INTERLACE) }; ++static const struct drm_display_mode drm_mode_288p = { ++ DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, ++ 288, 288 + 2, 288 + 2 + 3, 312, 0, 0) ++}; ++ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { [VC4_VEC_TV_MODE_NTSC] = { - .mode = &ntsc_mode, - .mode_set = vc4_vec_ntsc_mode_set, -+ .mode = &drm_mode_480i, ++ .interlaced_mode = &drm_mode_480i, ++ .progressive_mode = &drm_mode_240p, + .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, [VC4_VEC_TV_MODE_NTSC_J] = { - .mode = &ntsc_mode, - .mode_set = vc4_vec_ntsc_j_mode_set, -+ .mode = &drm_mode_480i, ++ .interlaced_mode = &drm_mode_480i, ++ .progressive_mode = &drm_mode_240p, + .config0 = VEC_CONFIG0_NTSC_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, + }, + [VC4_VEC_TV_MODE_NTSC_443] = { + /* NTSC with PAL chroma frequency */ -+ .mode = &drm_mode_480i, ++ .interlaced_mode = &drm_mode_480i, ++ .progressive_mode = &drm_mode_240p, + .config0 = VEC_CONFIG0_NTSC_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, + .custom_freq = 0x2a098acb, @@ -62535,31 +67204,36 @@ index bd5b8eb58b18..596b59ff6c9a 100644 [VC4_VEC_TV_MODE_PAL] = { - .mode = &pal_mode, - .mode_set = vc4_vec_pal_mode_set, -+ .mode = &drm_mode_576i, ++ .interlaced_mode = &drm_mode_576i, ++ .progressive_mode = &drm_mode_288p, + .config0 = VEC_CONFIG0_PAL_BDGHI_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, [VC4_VEC_TV_MODE_PAL_M] = { - .mode = &pal_mode, - .mode_set = vc4_vec_pal_m_mode_set, -+ .mode = &drm_mode_480i, ++ .interlaced_mode = &drm_mode_480i, ++ .progressive_mode = &drm_mode_240p, + .config0 = VEC_CONFIG0_PAL_M_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, + }, + [VC4_VEC_TV_MODE_PAL_N] = { -+ .mode = &drm_mode_576i, ++ .interlaced_mode = &drm_mode_576i, ++ .progressive_mode = &drm_mode_288p, + .config0 = VEC_CONFIG0_PAL_N_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, + }, + [VC4_VEC_TV_MODE_PAL60] = { + /* PAL-M with chroma frequency of regular PAL */ -+ .mode = &drm_mode_480i, ++ .interlaced_mode = &drm_mode_480i, ++ .progressive_mode = &drm_mode_240p, + .config0 = VEC_CONFIG0_PAL_M_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, + .custom_freq = 0x2a098acb, + }, + [VC4_VEC_TV_MODE_SECAM] = { -+ .mode = &drm_mode_576i, ++ .interlaced_mode = &drm_mode_576i, ++ .progressive_mode = &drm_mode_288p, + .config0 = VEC_CONFIG0_SECAM_STD, + .config1 = VEC_CONFIG1_C_CVBS_CVBS, + .custom_freq = 0x29c71c72, @@ -62607,7 +67281,43 @@ index bd5b8eb58b18..596b59ff6c9a 100644 static enum drm_connector_status vc4_vec_connector_detect(struct drm_connector *connector, bool force) { -@@ -331,17 +413,51 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector) +@@ -317,31 +420,74 @@ static void vc4_vec_connector_destroy(struct drm_connector *connector) + static int vc4_vec_connector_get_modes(struct drm_connector *connector) + { + struct drm_connector_state *state = connector->state; +- struct drm_display_mode *mode; +- +- mode = drm_mode_duplicate(connector->dev, +- vc4_vec_tv_modes[state->tv.mode].mode); +- if (!mode) { ++ struct drm_display_mode *interlaced_mode, *progressive_mode; ++ ++ interlaced_mode = ++ drm_mode_duplicate(connector->dev, ++ vc4_vec_tv_modes[state->tv.mode].interlaced_mode); ++ progressive_mode = ++ drm_mode_duplicate(connector->dev, ++ vc4_vec_tv_modes[state->tv.mode].progressive_mode); ++ if (!interlaced_mode || !progressive_mode) { + DRM_ERROR("Failed to create a new display mode\n"); ++ drm_mode_destroy(connector->dev, interlaced_mode); ++ drm_mode_destroy(connector->dev, progressive_mode); + return -ENOMEM; + } + +- drm_mode_probed_add(connector, mode); ++ if (connector->cmdline_mode.specified && ++ connector->cmdline_mode.refresh_specified && ++ !connector->cmdline_mode.interlace) ++ /* progressive mode set at boot, let's make it preferred */ ++ progressive_mode->type |= DRM_MODE_TYPE_PREFERRED; ++ else ++ /* otherwise, interlaced mode is preferred */ ++ interlaced_mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ drm_mode_probed_add(connector, interlaced_mode); ++ drm_mode_probed_add(connector, progressive_mode); + return 1; } @@ -62627,18 +67337,11 @@ index bd5b8eb58b18..596b59ff6c9a 100644 + struct drm_connector_state *new_state = + drm_atomic_get_new_connector_state(state, conn); + -+ const struct vc4_vec_tv_mode *vec_mode = -+ &vc4_vec_tv_modes[new_state->tv.mode]; -+ -+ if (new_state->crtc) { ++ if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) { + struct drm_crtc_state *crtc_state = + drm_atomic_get_new_crtc_state(state, new_state->crtc); + -+ if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode)) -+ return -EINVAL; -+ -+ if (old_state->tv.mode != new_state->tv.mode) -+ crtc_state->mode_changed = true; ++ crtc_state->mode_changed = true; + } + + return 0; @@ -62660,7 +67363,7 @@ index bd5b8eb58b18..596b59ff6c9a 100644 }; static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, -@@ -367,8 +483,7 @@ static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, +@@ -367,8 +513,7 @@ static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property, @@ -62670,7 +67373,7 @@ index bd5b8eb58b18..596b59ff6c9a 100644 drm_connector_attach_encoder(connector, vec->encoder); -@@ -401,6 +516,7 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) +@@ -401,6 +546,7 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) { struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); struct vc4_vec *vec = vc4_vec_encoder->vec; @@ -62678,9 +67381,15 @@ index bd5b8eb58b18..596b59ff6c9a 100644 int ret; ret = pm_runtime_get_sync(&vec->pdev->dev); -@@ -451,15 +567,20 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) +@@ -449,17 +595,25 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) + VEC_WRITE(VEC_CLMP0_START, 0xac); + VEC_WRITE(VEC_CLMP0_END, 0xec); VEC_WRITE(VEC_CONFIG2, - VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS); +- VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS); ++ VEC_CONFIG2_UV_DIG_DIS | ++ VEC_CONFIG2_RGB_DIG_DIS | ++ ((encoder->crtc->state->adjusted_mode.flags & ++ DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN)); VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD); - VEC_WRITE(VEC_DAC_CONFIG, - VEC_DAC_CONFIG_DAC_CTRL(0xc) | @@ -62704,10 +67413,17 @@ index bd5b8eb58b18..596b59ff6c9a 100644 VEC_WRITE(VEC_DAC_MISC, VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N); -@@ -474,49 +595,28 @@ static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, - return true; +@@ -467,34 +621,80 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) } + +-static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, +- const struct drm_display_mode *mode, +- struct drm_display_mode *adjusted_mode) +-{ +- return true; +-} +- -static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) @@ -62718,26 +67434,94 @@ index bd5b8eb58b18..596b59ff6c9a 100644 - vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; -} - --static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) --{ + static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) + { - const struct vc4_vec_tv_mode *vec_mode; - - vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; -- ++ const struct drm_display_mode *reference_mode = ++ vc4_vec_tv_modes[conn_state->tv.mode].interlaced_mode; ++ ++ if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock || ++ crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal || ++ crtc_state->adjusted_mode.crtc_hdisplay % 4 != 0 || ++ crtc_state->adjusted_mode.crtc_hsync_end - ++ crtc_state->adjusted_mode.crtc_hsync_start < 1) ++ return -EINVAL; + - if (conn_state->crtc && - !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode)) -- return -EINVAL; -- -- return 0; --} -- ++ switch (reference_mode->vtotal) { ++ case 525: ++ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 || ++ crtc_state->adjusted_mode.crtc_vdisplay > 253 || ++ crtc_state->adjusted_mode.crtc_vsync_start - ++ crtc_state->adjusted_mode.crtc_vdisplay < 1 || ++ crtc_state->adjusted_mode.crtc_vsync_end - ++ crtc_state->adjusted_mode.crtc_vsync_start != 3 || ++ crtc_state->adjusted_mode.crtc_vtotal - ++ crtc_state->adjusted_mode.crtc_vsync_end < 4 || ++ crtc_state->adjusted_mode.crtc_vtotal > 262) ++ return -EINVAL; ++ ++ if ((crtc_state->adjusted_mode.flags & ++ DRM_MODE_FLAG_INTERLACE) && ++ (crtc_state->adjusted_mode.vdisplay % 2 != 0 || ++ crtc_state->adjusted_mode.vsync_start % 2 != 1 || ++ crtc_state->adjusted_mode.vsync_end % 2 != 1 || ++ crtc_state->adjusted_mode.vtotal % 2 != 1)) ++ return -EINVAL; ++ ++ /* progressive mode is hard-wired to 262 total lines */ ++ if (!(crtc_state->adjusted_mode.flags & ++ DRM_MODE_FLAG_INTERLACE) && ++ crtc_state->adjusted_mode.crtc_vtotal != 262) ++ return -EINVAL; ++ ++ break; ++ ++ case 625: ++ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 || ++ crtc_state->adjusted_mode.crtc_vdisplay > 305 || ++ crtc_state->adjusted_mode.crtc_vsync_start - ++ crtc_state->adjusted_mode.crtc_vdisplay < 1 || ++ crtc_state->adjusted_mode.crtc_vsync_end - ++ crtc_state->adjusted_mode.crtc_vsync_start != 3 || ++ crtc_state->adjusted_mode.crtc_vtotal - ++ crtc_state->adjusted_mode.crtc_vsync_end < 2 || ++ crtc_state->adjusted_mode.crtc_vtotal > 312) ++ return -EINVAL; ++ ++ if ((crtc_state->adjusted_mode.flags & ++ DRM_MODE_FLAG_INTERLACE) && ++ (crtc_state->adjusted_mode.vdisplay % 2 != 0 || ++ crtc_state->adjusted_mode.vsync_start % 2 != 0 || ++ crtc_state->adjusted_mode.vsync_end % 2 != 0 || ++ crtc_state->adjusted_mode.vtotal % 2 != 1)) ++ return -EINVAL; ++ ++ /* progressive mode is hard-wired to 312 total lines */ ++ if (!(crtc_state->adjusted_mode.flags & ++ DRM_MODE_FLAG_INTERLACE) && ++ crtc_state->adjusted_mode.crtc_vtotal != 312) ++ return -EINVAL; ++ ++ break; ++ ++ default: + return -EINVAL; ++ } + + return 0; + } +@@ -502,21 +702,25 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { .disable = vc4_vec_encoder_disable, .enable = vc4_vec_encoder_enable, - .mode_fixup = vc4_vec_encoder_mode_fixup, -- .atomic_check = vc4_vec_encoder_atomic_check, +- .mode_fixup = vc4_vec_encoder_mode_fixup, + .atomic_check = vc4_vec_encoder_atomic_check, - .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, }; @@ -62768,7 +67552,7 @@ index bd5b8eb58b18..596b59ff6c9a 100644 }; static int vc4_vec_bind(struct device *dev, struct device *master, void *data) -@@ -546,6 +646,8 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) +@@ -546,6 +750,8 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) vec->encoder = &vc4_vec_encoder->base.base; vec->pdev = pdev; @@ -62777,7 +67561,7 @@ index bd5b8eb58b18..596b59ff6c9a 100644 vec->regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(vec->regs)) return PTR_ERR(vec->regs); -@@ -625,3 +727,10 @@ struct platform_driver vc4_vec_driver = { +@@ -625,3 +831,10 @@ struct platform_driver vc4_vec_driver = { .of_match_table = vc4_vec_dt_match, }, }; @@ -62970,7 +67754,7 @@ index 000000000000..e8d2b4b162f7 + VC_IMAGE_YUVINFO_CSC_REC_2020 = 9, +}; diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c -index f84b7e61311b..4bf74836bd53 100644 +index 9b2b99e85342..e156dd651c0c 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -95,12 +95,12 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) @@ -63116,10 +67900,10 @@ index 094fa4aa061d..c0a53a2cbbf1 100644 static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c -index 312ed0881a99..bc67f2b930e1 100644 +index 0e963fd7db17..cc7a05bac6b8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c -@@ -522,8 +522,10 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, +@@ -523,8 +523,10 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, @@ -63131,7 +67915,7 @@ index 312ed0881a99..bc67f2b930e1 100644 struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc); int connector_mask = drm_connector_mask(&du->connector); bool has_primary = new_state->plane_mask & -@@ -552,13 +554,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, +@@ -553,13 +555,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc, @@ -63312,7 +68096,7 @@ index 5259ff2825f9..904f62f3bfc1 100644 struct drm_pending_vblank_event *event = crtc->state->event; diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 136b58a91c04..fae50dbda6aa 100644 +index bb096dfb7b36..09d605f73e10 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -221,6 +221,9 @@ @@ -63325,7 +68109,7 @@ index 136b58a91c04..fae50dbda6aa 100644 #define USB_VENDOR_ID_BELKIN 0x050d #define USB_DEVICE_ID_FLIP_KVM 0x3201 -@@ -1268,6 +1271,9 @@ +@@ -1273,6 +1276,9 @@ #define USB_VENDOR_ID_XAT 0x2505 #define USB_DEVICE_ID_XAT_CSR 0x0220 @@ -63336,7 +68120,7 @@ index 136b58a91c04..fae50dbda6aa 100644 #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 be53c723c729..9f9d5778114e 100644 +index 2ab71d717bb0..cc9aaea2d9ab 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -41,6 +41,7 @@ static const struct hid_device_id hid_quirks[] = { @@ -63347,7 +68131,7 @@ index be53c723c729..9f9d5778114e 100644 { 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 }, -@@ -193,6 +194,7 @@ static const struct hid_device_id hid_quirks[] = { +@@ -195,6 +196,7 @@ static const struct hid_device_id hid_quirks[] = { { 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_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_GROUP_AUDIO), HID_QUIRK_NOGET }, @@ -63356,7 +68140,7 @@ index be53c723c729..9f9d5778114e 100644 { 0 } }; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index 8d4ac4b9fb9d..5ab69fc58d1b 100644 +index 009a0469d54f..1f0e61d1312d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -45,7 +45,7 @@ @@ -63388,10 +68172,10 @@ index 8d4ac4b9fb9d..5ab69fc58d1b 100644 ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index a850e4f0e0bd..ecf08982c352 100644 +index 8bcffda38cb7..f2057f1ad090 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig -@@ -1489,6 +1489,17 @@ config SENSORS_RASPBERRYPI_HWMON +@@ -1499,6 +1499,17 @@ config SENSORS_RASPBERRYPI_HWMON This driver can also be built as a module. If so, the module will be called raspberrypi-hwmon. @@ -63410,7 +68194,7 @@ index a850e4f0e0bd..ecf08982c352 100644 tristate "Kontron sl28cpld hardware monitoring driver" depends on MFD_SL28CPLD || COMPILE_TEST diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index 9db2903b61e5..dc68c9788a5e 100644 +index 95908c478b94..b1489a08325b 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -157,6 +157,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o @@ -63938,7 +68722,7 @@ index 000000000000..8483b6ce1db8 +MODULE_DESCRIPTION("Raspberry Pi PoE HAT fan driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 14d45b453a61..4c3010089b7f 100644 +index 5763a1e9360b..e5582930c720 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -9,6 +9,25 @@ menu "I2C Hardware Bus support" @@ -63968,7 +68752,7 @@ index 14d45b453a61..4c3010089b7f 100644 tristate "ALI 1535" depends on PCI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index f36a05632f85..fe09307c1945 100644 +index 280e05622d50..42c272f5205b 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -3,6 +3,8 @@ @@ -64499,10 +69283,10 @@ index 000000000000..962f2e5c7455 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index 37443edbf754..5b2589b6b9cc 100644 +index ad3b124a2e37..340f29483a61 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -51,6 +51,18 @@ +@@ -56,6 +56,22 @@ #define BCM2835_I2C_CDIV_MIN 0x0002 #define BCM2835_I2C_CDIV_MAX 0xFFFE @@ -64510,6 +69294,10 @@ index 37443edbf754..5b2589b6b9cc 100644 +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); + ++static unsigned int clk_tout_ms = 35; /* SMBUs-recommended 35ms */ ++module_param(clk_tout_ms, uint, 0644); ++MODULE_PARM_DESC(clk_tout_ms, "clock-stretch timeout (mS)"); ++ +#define BCM2835_DEBUG_MAX 512 +struct bcm2835_debug { + struct i2c_msg *msg; @@ -64521,7 +69309,7 @@ index 37443edbf754..5b2589b6b9cc 100644 struct bcm2835_i2c_dev { struct device *dev; void __iomem *regs; -@@ -63,8 +75,78 @@ struct bcm2835_i2c_dev { +@@ -68,8 +84,78 @@ struct bcm2835_i2c_dev { u32 msg_err; u8 *msg_buf; size_t msg_buf_remaining; @@ -64600,7 +69388,7 @@ index 37443edbf754..5b2589b6b9cc 100644 static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, u32 reg, u32 val) { -@@ -106,6 +188,7 @@ static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate, +@@ -111,6 +197,7 @@ static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw); u32 redl, fedl; @@ -64608,25 +69396,25 @@ index 37443edbf754..5b2589b6b9cc 100644 u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate); if (divider == -EINVAL) -@@ -129,6 +212,17 @@ static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate, +@@ -134,6 +221,17 @@ static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate, bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL, (fedl << BCM2835_I2C_FEDL_SHIFT) | (redl << BCM2835_I2C_REDL_SHIFT)); + + /* -+ * Set the clock stretch timeout to the SMBUs-recommended 35ms. ++ * Set the clock stretch timeout. + */ -+ if (rate > 0xffff*1000/35) ++ if (rate > 0xffff*1000/clk_tout_ms) + clk_tout = 0xffff; + else -+ clk_tout = 35*rate/1000; ++ clk_tout = clk_tout_ms*rate/1000; + + bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_CLKT, clk_tout); + return 0; } -@@ -252,6 +346,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) +@@ -257,6 +355,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); @@ -64634,7 +69422,7 @@ index 37443edbf754..5b2589b6b9cc 100644 } static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c_dev *i2c_dev) -@@ -278,6 +373,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) +@@ -283,6 +382,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) u32 val, err; val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); @@ -64642,7 +69430,7 @@ index 37443edbf754..5b2589b6b9cc 100644 err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); if (err) { -@@ -344,6 +440,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], +@@ -349,6 +449,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], unsigned long time_left; int i; @@ -64656,7 +69444,7 @@ index 37443edbf754..5b2589b6b9cc 100644 for (i = 0; i < (num - 1); i++) if (msgs[i].flags & I2C_M_RD) { dev_warn_once(i2c_dev->dev, -@@ -362,6 +465,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], +@@ -367,6 +474,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], bcm2835_i2c_finish_transfer(i2c_dev); @@ -64667,7 +69455,7 @@ index 37443edbf754..5b2589b6b9cc 100644 if (!time_left) { bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); -@@ -372,7 +479,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], +@@ -377,7 +488,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (!i2c_dev->msg_err) return num; @@ -64880,7 +69668,7 @@ index 000000000000..6a416769065d +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c -index 6ff81d48da86..d4060bc89ce9 100644 +index 6ff81d48da86..9be7a6aba409 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -69,6 +69,8 @@ @@ -64892,7 +69680,13 @@ index 6ff81d48da86..d4060bc89ce9 100644 enum edt_pmode { EDT_PMODE_NOT_SUPPORTED, EDT_PMODE_HIBERNATE, -@@ -126,6 +128,9 @@ struct edt_ft5x06_ts_data { +@@ -121,11 +123,15 @@ struct edt_ft5x06_ts_data { + int offset_y; + int report_rate; + int max_support_points; ++ unsigned int known_ids; + + char name[EDT_NAME_LEN]; struct edt_reg_addr reg_addr; enum edt_ver version; @@ -64902,7 +69696,62 @@ index 6ff81d48da86..d4060bc89ce9 100644 }; struct edt_i2c_chip_data { -@@ -275,6 +280,22 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) +@@ -192,6 +198,10 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + int i, type, x, y, id; + int offset, tplen, datalen, crclen; + int error; ++ unsigned int active_ids = 0, known_ids = tsdata->known_ids; ++ long released_ids; ++ int b = 0; ++ unsigned int num_points; + + switch (tsdata->version) { + case EDT_M06: +@@ -239,9 +249,15 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + + if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen)) + goto out; ++ num_points = tsdata->max_support_points; ++ } else { ++ /* Register 2 is TD_STATUS, containing the number of touch ++ * points. ++ */ ++ num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points); + } + +- for (i = 0; i < tsdata->max_support_points; i++) { ++ for (i = 0; i < num_points; i++) { + u8 *buf = &rdbuf[i * tplen + offset]; + + type = buf[0] >> 6; +@@ -263,10 +279,25 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + + input_mt_slot(tsdata->input, id); + if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, +- type != TOUCH_EVENT_UP)) ++ type != TOUCH_EVENT_UP)) { + touchscreen_report_pos(tsdata->input, &tsdata->prop, + x, y, true); ++ active_ids |= BIT(id); ++ } else { ++ known_ids &= ~BIT(id); ++ } ++ } ++ ++ /* One issue with the device is the TOUCH_UP message is not always ++ * returned. Instead track which ids we know about and report when they ++ * are no longer updated ++ */ ++ released_ids = known_ids & ~active_ids; ++ for_each_set_bit_from(b, &released_ids, tsdata->max_support_points) { ++ input_mt_slot(tsdata->input, b); ++ input_mt_report_slot_inactive(tsdata->input); + } ++ tsdata->known_ids = active_ids; + + input_mt_report_pointer_emulation(tsdata->input, true); + input_sync(tsdata->input); +@@ -275,6 +306,22 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) return IRQ_HANDLED; } @@ -64925,7 +69774,7 @@ index 6ff81d48da86..d4060bc89ce9 100644 static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, u8 addr, u8 value) { -@@ -1221,17 +1242,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, +@@ -1221,17 +1268,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, i2c_set_clientdata(client, tsdata); @@ -64963,7 +69812,7 @@ index 6ff81d48da86..d4060bc89ce9 100644 } error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group); -@@ -1257,6 +1288,10 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client) +@@ -1257,6 +1314,10 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client) { struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); @@ -65613,38 +70462,23 @@ index 39761d190545..9766d8b50778 100644 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c -index 3e7d4b20ab34..0b821a5b2db8 100644 +index 4229b9b5da98..2358ec3431ad 100644 --- a/drivers/mailbox/mailbox.c +++ b/drivers/mailbox/mailbox.c @@ -82,12 +82,9 @@ static void msg_submit(struct mbox_chan *chan) exit: spin_unlock_irqrestore(&chan->lock, flags); -- /* kick start the timer immediately to avoid delays */ - if (!err && (chan->txdone_method & TXDONE_BY_POLL)) { -- /* but only if not already active */ -- if (!hrtimer_active(&chan->mbox->poll_hrt)) -- hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL); -- } + if (!err && (chan->txdone_method & TXDONE_BY_POLL)) -+ /* kick start the timer immediately to avoid delays */ -+ hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL); + /* kick start the timer immediately to avoid delays */ +- spin_lock_irqsave(&chan->mbox->poll_hrt_lock, flags); + hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL); +- spin_unlock_irqrestore(&chan->mbox->poll_hrt_lock, flags); +- } } static void tx_tick(struct mbox_chan *chan, int r) -@@ -125,10 +122,11 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer) - struct mbox_chan *chan = &mbox->chans[i]; - - if (chan->active_req && chan->cl) { -- resched = true; - txdone = chan->mbox->ops->last_tx_done(chan); - if (txdone) - tx_tick(chan, 0); -+ else -+ resched = true; - } - } - diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 72350343a56a..3c6a74b29683 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c @@ -65831,9 +70665,18 @@ index 4498d14d3429..4103690a71df 100644 mutex_unlock(&state->mutex); diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c -index 4771d0ef2c46..79faa8cce94e 100644 +index 4771d0ef2c46..7f0fdd6fd7bc 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c +@@ -55,7 +55,7 @@ + #define IMX219_VTS_30FPS_640x480 0x06e3 + #define IMX219_VTS_MAX 0xffff + +-#define IMX219_VBLANK_MIN 4 ++#define IMX219_VBLANK_MIN 32 + + /*Frame Length Line*/ + #define IMX219_FLL_MIN 0x08a6 @@ -118,6 +118,16 @@ #define IMX219_PIXEL_ARRAY_WIDTH 3280U #define IMX219_PIXEL_ARRAY_HEIGHT 2464U @@ -65860,6 +70703,15 @@ index 4771d0ef2c46..79faa8cce94e 100644 struct v4l2_mbus_framefmt fmt; +@@ -671,7 +681,7 @@ static void imx219_set_default_format(struct imx219 *imx219) + + fmt = &imx219->fmt; + fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10; +- fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); + fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, + fmt->colorspace, @@ -685,18 +695,26 @@ static void imx219_set_default_format(struct imx219 *imx219) static int imx219_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { @@ -65919,7 +70771,7 @@ index 4771d0ef2c46..79faa8cce94e 100644 return 0; } -@@ -819,16 +848,29 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd, +@@ -819,23 +848,36 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd, { struct imx219 *imx219 = to_imx219(sd); @@ -65932,7 +70784,11 @@ index 4771d0ef2c46..79faa8cce94e 100644 + if (fse->pad == IMAGE_PAD) { + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; -+ + +- fse->min_width = supported_modes[fse->index].width; +- fse->max_width = fse->min_width; +- fse->min_height = supported_modes[fse->index].height; +- fse->max_height = fse->min_height; + if (fse->code != imx219_get_format_code(imx219, fse->code)) + return -EINVAL; + @@ -65943,11 +70799,7 @@ index 4771d0ef2c46..79faa8cce94e 100644 + } else { + if (fse->code != MEDIA_BUS_FMT_SENSOR_DATA || fse->index > 0) + return -EINVAL; - -- fse->min_width = supported_modes[fse->index].width; -- fse->max_width = fse->min_width; -- fse->min_height = supported_modes[fse->index].height; -- fse->max_height = fse->min_height; ++ + fse->min_width = IMX219_EMBEDDED_LINE_WIDTH; + fse->max_width = fse->min_width; + fse->min_height = IMX219_NUM_EMBEDDED_LINES; @@ -65956,6 +70808,14 @@ index 4771d0ef2c46..79faa8cce94e 100644 return 0; } + + static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt) + { +- fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); + fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, + fmt->colorspace, @@ -843,9 +885,9 @@ static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt) fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace); } @@ -66154,7 +71014,7 @@ index 4771d0ef2c46..79faa8cce94e 100644 dev_err(dev, "failed to init entity pads: %d\n", ret); goto error_handler_free; diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c -index adcddf3204f7..a26106c41cc6 100644 +index adcddf3204f7..def912308daa 100644 --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -1,6 +1,12 @@ @@ -66732,7 +71592,7 @@ index adcddf3204f7..a26106c41cc6 100644 - fmt->format.code = imx290_formats[i].code; + fmt->format.code = imx290->formats[i].code; fmt->format.field = V4L2_FIELD_NONE; -+ fmt->format.colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->format.colorspace = V4L2_COLORSPACE_RAW; + fmt->format.ycbcr_enc = + V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace); + fmt->format.quantization = @@ -67141,10 +72001,10 @@ index adcddf3204f7..a26106c41cc6 100644 static struct i2c_driver imx290_i2c_driver = { diff --git a/drivers/media/i2c/imx477.c b/drivers/media/i2c/imx477.c new file mode 100644 -index 000000000000..05cb530d331e +index 000000000000..b2d4fb54cb1e --- /dev/null +++ b/drivers/media/i2c/imx477.c -@@ -0,0 +1,2284 @@ +@@ -0,0 +1,2309 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * A V4L2 driver for Sony IMX477 cameras. @@ -67172,6 +72032,10 @@ index 000000000000..05cb530d331e +module_param(dpc_enable, int, 0644); +MODULE_PARM_DESC(dpc_enable, "Enable on-sensor DPC"); + ++static int trigger_mode; ++module_param(trigger_mode, int, 0644); ++MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink"); ++ +#define IMX477_REG_VALUE_08BIT 1 +#define IMX477_REG_VALUE_16BIT 2 + @@ -67245,6 +72109,12 @@ index 000000000000..05cb530d331e +#define IMX477_TEST_PATTERN_B_DEFAULT 0 +#define IMX477_TEST_PATTERN_GB_DEFAULT 0 + ++/* Trigger mode */ ++#define IMX477_REG_MC_MODE 0x3f0b ++#define IMX477_REG_MS_SEL 0x3041 ++#define IMX477_REG_XVS_IO_CTRL 0x3040 ++#define IMX477_REG_EXTOUT_EN 0x4b81 ++ +/* Embedded metadata stream structure */ +#define IMX477_EMBEDDED_LINE_WIDTH 16384 +#define IMX477_NUM_EMBEDDED_LINES 1 @@ -68618,7 +73488,7 @@ index 000000000000..05cb530d331e + +static void imx477_reset_colorspace(struct v4l2_mbus_framefmt *fmt) +{ -+ fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); + fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, + fmt->colorspace, @@ -68866,6 +73736,21 @@ index 000000000000..05cb530d331e + imx477_write_reg(imx477, 0x0b05, IMX477_REG_VALUE_08BIT, !!dpc_enable); + imx477_write_reg(imx477, 0x0b06, IMX477_REG_VALUE_08BIT, !!dpc_enable); + ++ /* Set vsync trigger mode */ ++ if (trigger_mode != 0) { ++ /* trigger_mode == 1 for source, 2 for sink */ ++ const u32 val = (trigger_mode == 1) ? 1 : 0; ++ ++ imx477_write_reg(imx477, IMX477_REG_MC_MODE, ++ IMX477_REG_VALUE_08BIT, 1); ++ imx477_write_reg(imx477, IMX477_REG_MS_SEL, ++ IMX477_REG_VALUE_08BIT, val); ++ imx477_write_reg(imx477, IMX477_REG_XVS_IO_CTRL, ++ IMX477_REG_VALUE_08BIT, val); ++ imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, ++ IMX477_REG_VALUE_08BIT, val); ++ } ++ + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx477->sd.ctrl_handler); + if (ret) @@ -69431,7 +74316,7 @@ index 000000000000..05cb530d331e +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/imx519.c b/drivers/media/i2c/imx519.c new file mode 100644 -index 000000000000..4e98704a6834 +index 000000000000..675b4a94e065 --- /dev/null +++ b/drivers/media/i2c/imx519.c @@ -0,0 +1,2091 @@ @@ -70754,7 +75639,7 @@ index 000000000000..4e98704a6834 + +static void imx519_reset_colorspace(struct v4l2_mbus_framefmt *fmt) +{ -+ fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); + fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, + fmt->colorspace, @@ -72834,10 +77719,10 @@ index 000000000000..96d676123d5e +#endif /* IRS1125 */ + diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c -index e7d2e5b4ad4b..98a5329d68fb 100644 +index e7d2e5b4ad4b..3b7a15852c5d 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c -@@ -21,6 +21,7 @@ +@@ -21,21 +21,34 @@ #include #include @@ -72845,8 +77730,9 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 #include #include #include -@@ -28,14 +29,25 @@ + #include #include ++#include #include #include +#include @@ -72871,7 +77757,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 #define MIPI_CTRL00_BUS_IDLE BIT(2) #define MIPI_CTRL00_CLOCK_LANE_DISABLE BIT(0) -@@ -44,48 +56,75 @@ +@@ -44,48 +57,89 @@ #define OV5647_REG_CHIPID_H 0x300A #define OV5647_REG_CHIPID_L 0x300B #define OV5640_REG_PAD_OUT 0x300D @@ -72883,6 +77769,8 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 +#define OV5647_REG_GAIN_LO 0x350B +#define OV5647_REG_VTS_HI 0x380e +#define OV5647_REG_VTS_LO 0x380f ++#define OV5647_REG_VFLIP 0x3820 ++#define OV5647_REG_HFLIP 0x3821 #define OV5647_REG_FRAME_OFF_NUMBER 0x4202 #define OV5647_REG_MIPI_CTRL00 0x4800 #define OV5647_REG_MIPI_CTRL14 0x4814 @@ -72924,6 +77812,15 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 +#define OV5647_EXPOSURE_STEP 1 +#define OV5647_EXPOSURE_DEFAULT 1000 +#define OV5647_EXPOSURE_MAX 65535 ++ ++/* regulator supplies */ ++static const char * const ov5647_supply_names[] = { ++ "avdd", /* Analog power */ ++ "dovdd", /* Digital I/O power */ ++ "dvdd", /* Digital core power */ ++}; ++ ++#define OV5647_NUM_SUPPLIES ARRAY_SIZE(ov5647_supply_names) struct regval_list { u16 addr; @@ -72956,17 +77853,20 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 int power_count; struct clk *xclk; + struct gpio_desc *pwdn; ++ struct regulator_bulk_data supplies[OV5647_NUM_SUPPLIES]; + unsigned int flags; + struct v4l2_ctrl_handler ctrls; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *exposure; ++ struct v4l2_ctrl *hflip; ++ struct v4l2_ctrl *vflip; + bool write_mode_regs; }; static inline struct ov5647 *to_state(struct v4l2_subdev *sd) -@@ -105,7 +144,7 @@ static struct regval_list sensor_oe_enable_regs[] = { +@@ -105,7 +159,7 @@ static struct regval_list sensor_oe_enable_regs[] = { {0x3002, 0xe4}, }; @@ -72975,7 +77875,15 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 {0x0100, 0x00}, {0x0103, 0x01}, {0x3034, 0x08}, -@@ -120,7 +159,6 @@ static struct regval_list ov5647_640x480[] = { +@@ -113,14 +167,13 @@ static struct regval_list ov5647_640x480[] = { + {0x3036, 0x46}, + {0x303c, 0x11}, + {0x3106, 0xf5}, +- {0x3821, 0x07}, ++ {0x3821, 0x01}, + {0x3820, 0x41}, + {0x3827, 0xec}, + {0x370c, 0x0f}, {0x3612, 0x59}, {0x3618, 0x00}, {0x5000, 0x06}, @@ -72983,7 +77891,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 {0x5002, 0x41}, {0x5003, 0x08}, {0x5a00, 0x08}, -@@ -138,8 +176,6 @@ static struct regval_list ov5647_640x480[] = { +@@ -138,8 +191,6 @@ static struct regval_list ov5647_640x480[] = { {0x3b07, 0x0c}, {0x380c, 0x07}, {0x380d, 0x68}, @@ -72992,7 +77900,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 {0x3814, 0x31}, {0x3815, 0x31}, {0x3708, 0x64}, -@@ -196,6 +232,517 @@ static struct regval_list ov5647_640x480[] = { +@@ -196,6 +247,517 @@ static struct regval_list ov5647_640x480[] = { {0x0100, 0x01}, }; @@ -73004,7 +77912,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + {0x3036, 0x69}, + {0x303c, 0x11}, + {0x3106, 0xf5}, -+ {0x3821, 0x06}, ++ {0x3821, 0x00}, + {0x3820, 0x00}, + {0x3827, 0xec}, + {0x370c, 0x03}, @@ -73093,7 +78001,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + {0x3036, 0x62}, + {0x303c, 0x11}, + {0x3106, 0xf5}, -+ {0x3821, 0x06}, ++ {0x3821, 0x00}, + {0x3820, 0x00}, + {0x3827, 0xec}, + {0x370c, 0x03}, @@ -73257,7 +78165,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + {0x4800, 0x24}, + {0x3503, 0x03}, + {0x3820, 0x41}, -+ {0x3821, 0x07}, ++ {0x3821, 0x01}, + {0x350A, 0x00}, + {0x350B, 0x10}, + {0x3500, 0x00}, @@ -73273,7 +78181,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + {0x3035, 0x11}, + {0x3036, 0x46}, + {0x303c, 0x11}, -+ {0x3821, 0x07}, ++ {0x3821, 0x01}, + {0x3820, 0x41}, + {0x370c, 0x03}, + {0x3612, 0x59}, @@ -73365,7 +78273,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR8_1X8, -+ .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 640, + .height = 480 @@ -73391,7 +78299,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, -+ .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 2592, + .height = 1944 @@ -73415,7 +78323,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, -+ .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 1920, + .height = 1080 @@ -73438,7 +78346,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, -+ .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 1296, + .height = 972 @@ -73462,7 +78370,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + { + .format = { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, -+ .colorspace = V4L2_COLORSPACE_SRGB, ++ .colorspace = V4L2_COLORSPACE_RAW, + .field = V4L2_FIELD_NONE, + .width = 640, + .height = 480 @@ -73510,7 +78418,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val) { int ret; -@@ -203,9 +750,18 @@ static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val) +@@ -203,9 +765,18 @@ static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val) struct i2c_client *client = v4l2_get_subdevdata(sd); ret = i2c_master_send(client, data, 3); @@ -73530,7 +78438,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 return ret; } -@@ -217,16 +773,31 @@ static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val) +@@ -217,16 +788,31 @@ static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val) struct i2c_client *client = v4l2_get_subdevdata(sd); ret = i2c_master_send(client, data_w, 2); @@ -73564,7 +78472,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 return ret; } -@@ -258,11 +829,68 @@ static int ov5647_set_virtual_channel(struct v4l2_subdev *sd, int channel) +@@ -258,11 +844,68 @@ static int ov5647_set_virtual_channel(struct v4l2_subdev *sd, int channel) return ov5647_write(sd, OV5647_REG_MIPI_CTRL14, channel_id | (channel << 6)); } @@ -73634,7 +78542,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 if (ret < 0) return ret; -@@ -306,44 +934,6 @@ static int set_sw_standby(struct v4l2_subdev *sd, bool standby) +@@ -306,44 +949,6 @@ static int set_sw_standby(struct v4l2_subdev *sd, bool standby) return ov5647_write(sd, OV5647_SW_STANDBY, rdval); } @@ -73679,10 +78587,17 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) { int ret = 0; -@@ -355,6 +945,11 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) +@@ -355,33 +960,57 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) if (on && !ov5647->power_count) { dev_dbg(&client->dev, "OV5647 power on\n"); ++ ret = regulator_bulk_enable(OV5647_NUM_SUPPLIES, ++ ov5647->supplies); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to enable regulators\n"); ++ goto out; ++ } ++ + if (ov5647->pwdn) { + gpiod_set_value_cansleep(ov5647->pwdn, 0); + msleep(PWDN_ACTIVE_DELAY_MS); @@ -73690,8 +78605,10 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + ret = clk_prepare_enable(ov5647->xclk); if (ret < 0) { ++ regulator_bulk_disable(OV5647_NUM_SUPPLIES, ++ ov5647->supplies); dev_err(&client->dev, "clk prepare enable failed\n"); -@@ -362,7 +957,7 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) + goto out; } ret = ov5647_write_array(sd, sensor_oe_enable_regs, @@ -73699,8 +78616,10 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + ARRAY_SIZE(sensor_oe_enable_regs)); if (ret < 0) { clk_disable_unprepare(ov5647->xclk); ++ regulator_bulk_disable(OV5647_NUM_SUPPLIES, ++ ov5647->supplies); dev_err(&client->dev, -@@ -370,18 +965,24 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) + "write sensor_oe_enable_regs error\n"); goto out; } @@ -73711,6 +78630,8 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + ret = ov5647_stream_off(sd); if (ret < 0) { clk_disable_unprepare(ov5647->xclk); ++ regulator_bulk_disable(OV5647_NUM_SUPPLIES, ++ ov5647->supplies); dev_err(&client->dev, "Camera not available, check Power\n"); goto out; @@ -73727,16 +78648,18 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 if (ret < 0) dev_dbg(&client->dev, "disable oe failed\n"); -@@ -392,6 +993,8 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) +@@ -392,6 +1021,10 @@ static int ov5647_sensor_power(struct v4l2_subdev *sd, int on) dev_dbg(&client->dev, "soft stby failed\n"); clk_disable_unprepare(ov5647->xclk); + + gpiod_set_value_cansleep(ov5647->pwdn, 1); ++ ++ regulator_bulk_disable(OV5647_NUM_SUPPLIES, ov5647->supplies); } /* Update the power count. */ -@@ -437,14 +1040,76 @@ static const struct v4l2_subdev_core_ops ov5647_subdev_core_ops = { +@@ -437,34 +1070,274 @@ static const struct v4l2_subdev_core_ops ov5647_subdev_core_ops = { .g_register = ov5647_sensor_get_register, .s_register = ov5647_sensor_set_register, #endif @@ -73815,19 +78738,49 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 } static const struct v4l2_subdev_video_ops ov5647_subdev_video_ops = { -@@ -455,16 +1120,163 @@ static int ov5647_enum_mbus_code(struct v4l2_subdev *sd, + .s_stream = ov5647_s_stream, + }; + ++/* This function returns the mbus code for the current settings of the ++ HFLIP and VFLIP controls. */ ++ ++static u32 ov5647_get_mbus_code(struct v4l2_subdev *sd, int mode_8bit) ++{ ++ struct ov5647 *state = to_state(sd); ++ /* The control values are only 0 or 1. */ ++ int index = state->hflip->val | (state->vflip->val << 1); ++ ++ static const u32 codes[2][4] = { ++ { ++ MEDIA_BUS_FMT_SGBRG10_1X10, ++ MEDIA_BUS_FMT_SBGGR10_1X10, ++ MEDIA_BUS_FMT_SRGGB10_1X10, ++ MEDIA_BUS_FMT_SGRBG10_1X10 ++ }, ++ { ++ MEDIA_BUS_FMT_SGBRG8_1X8, ++ MEDIA_BUS_FMT_SBGGR8_1X8, ++ MEDIA_BUS_FMT_SRGGB8_1X8, ++ MEDIA_BUS_FMT_SGRBG8_1X8 ++ } ++ }; ++ ++ return codes[mode_8bit][index]; ++} ++ + static int ov5647_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { - if (code->index > 0) + if (code->index == 0 && ARRAY_SIZE(supported_modes_8bit)) -+ code->code = MEDIA_BUS_FMT_SBGGR8_1X8; ++ code->code = ov5647_get_mbus_code(sd, 1); + else if (code->index == 0 && ARRAY_SIZE(supported_modes_8bit) == 0 && + ARRAY_SIZE(supported_modes_10bit)) -+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ code->code = ov5647_get_mbus_code(sd, 0); + else if (code->index == 1 && ARRAY_SIZE(supported_modes_8bit) && + ARRAY_SIZE(supported_modes_10bit)) -+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10; ++ code->code = ov5647_get_mbus_code(sd, 0); + else + return -EINVAL; + @@ -73840,11 +78793,11 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 +{ + struct ov5647_mode *mode = NULL; + -+ if (fse->code == MEDIA_BUS_FMT_SBGGR8_1X8) { ++ if (fse->code == ov5647_get_mbus_code(sd, 1)) { + if (fse->index >= ARRAY_SIZE(supported_modes_8bit)) + return -EINVAL; + mode = &supported_modes_8bit[fse->index]; -+ } else if (fse->code == MEDIA_BUS_FMT_SBGGR10_1X10) { ++ } else if (fse->code == ov5647_get_mbus_code(sd, 0)) { + if (fse->index >= ARRAY_SIZE(supported_modes_10bit)) + return -EINVAL; + mode = &supported_modes_10bit[fse->index]; @@ -73888,9 +78841,9 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + format.width, format.height, + format->format.width, + format->format.height); -+ if (format->format.code == MEDIA_BUS_FMT_SBGGR8_1X8 && mode_8bit) ++ if (format->format.code == ov5647_get_mbus_code(sd, 1) && mode_8bit) + mode = mode_8bit; -+ else if (format->format.code == MEDIA_BUS_FMT_SBGGR10_1X10 && ++ else if (format->format.code == ov5647_get_mbus_code(sd, 0) && + mode_10bit) + mode = mode_10bit; + else if (mode_10bit) @@ -73904,6 +78857,8 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + } + + *fmt = mode->format; ++ /* The mbus code we pass back must reflect the current H/VFLIP settings. */ ++ fmt->code = ov5647_get_mbus_code(sd, mode == mode_8bit); + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + framefmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + *framefmt = format->format; @@ -73966,6 +78921,8 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + *fmt = *v4l2_subdev_get_try_format(sd, cfg, format->pad); + else + *fmt = state->mode->format; ++ /* The mbus code we pass back must reflect the current H/VFLIP settings. */ ++ fmt->code = ov5647_get_mbus_code(sd, fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8); + + mutex_unlock(&state->lock); @@ -73981,7 +78938,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 }; static const struct v4l2_subdev_ops ov5647_subdev_ops = { -@@ -510,18 +1322,15 @@ static int ov5647_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +@@ -510,18 +1383,15 @@ static int ov5647_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) v4l2_subdev_get_try_format(sd, fh->pad, 0); struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->pad, 0); @@ -73991,13 +78948,13 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 - crop->top = OV5647_ROW_START_DEF; - crop->width = OV5647_WINDOW_WIDTH_DEF; - crop->height = OV5647_WINDOW_HEIGHT_DEF; -- -- format->code = MEDIA_BUS_FMT_SBGGR8_1X8; + crop->left = OV5647_PIXEL_ARRAY_LEFT; + crop->top = OV5647_PIXEL_ARRAY_TOP; + crop->width = OV5647_PIXEL_ARRAY_WIDTH; + crop->height = OV5647_PIXEL_ARRAY_HEIGHT; +- format->code = MEDIA_BUS_FMT_SBGGR8_1X8; +- - format->width = OV5647_WINDOW_WIDTH_DEF; - format->height = OV5647_WINDOW_HEIGHT_DEF; - format->field = V4L2_FIELD_NONE; @@ -74007,7 +78964,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 return 0; } -@@ -530,7 +1339,7 @@ static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = { +@@ -530,7 +1400,7 @@ static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = { .open = ov5647_open, }; @@ -74016,7 +78973,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 { struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *ep; -@@ -543,10 +1352,150 @@ static int ov5647_parse_dt(struct device_node *np) +@@ -543,10 +1413,188 @@ static int ov5647_parse_dt(struct device_node *np) ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg); @@ -74092,6 +79049,25 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + return ret; +} + ++static int ov5647_s_flip( struct v4l2_subdev *sd, u16 reg, u32 ctrl_val) ++{ ++ int ret; ++ u8 reg_val; ++ ++ /* Set or clear bit 1 and leave everything else alone. */ ++ ret = ov5647_read(sd, reg, ®_val); ++ if (ret == 0) { ++ if (ctrl_val) ++ reg_val |= 2; ++ else ++ reg_val &= ~2; ++ ++ ret = ov5647_write(sd, reg, reg_val); ++ } ++ ++ return ret; ++} ++ +static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov5647 *state = container_of(ctrl->handler, @@ -74149,6 +79125,13 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + ret = ov5647_write16(sd, OV5647_REG_VTS_HI, + state->mode->format.height + ctrl->val); + break; ++ case V4L2_CID_HFLIP: ++ /* There's an in-built hflip in the sensor, so account for that here. */ ++ ov5647_s_flip(sd, OV5647_REG_HFLIP, !ctrl->val); ++ break; ++ case V4L2_CID_VFLIP: ++ ov5647_s_flip(sd, OV5647_REG_VFLIP, ctrl->val); ++ break; + default: + dev_info(&client->dev, + "ctrl(id:0x%x,val:0x%x) is not handled\n", @@ -74163,11 +79146,23 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 +static const struct v4l2_ctrl_ops ov5647_ctrl_ops = { + .s_ctrl = ov5647_s_ctrl, +}; ++ ++static int ov5647_configure_regulators(struct device *dev, ++ struct ov5647 *ov5647) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < OV5647_NUM_SUPPLIES; i++) ++ ov5647->supplies[i].supply = ov5647_supply_names[i]; ++ ++ return devm_regulator_bulk_get(dev, OV5647_NUM_SUPPLIES, ++ ov5647->supplies); ++} + static int ov5647_probe(struct i2c_client *client) { struct device *dev = &client->dev; -@@ -555,13 +1504,15 @@ static int ov5647_probe(struct i2c_client *client) +@@ -555,13 +1603,15 @@ static int ov5647_probe(struct i2c_client *client) struct v4l2_subdev *sd; struct device_node *np = client->dev.of_node; u32 xclk_freq; @@ -74184,18 +79179,24 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 if (ret) { dev_err(dev, "DT parsing error: %d\n", ret); return ret; -@@ -581,12 +1532,97 @@ static int ov5647_probe(struct i2c_client *client) +@@ -581,12 +1631,113 @@ static int ov5647_probe(struct i2c_client *client) return -EINVAL; } + /* Request the power down GPIO asserted */ + sensor->pwdn = devm_gpiod_get_optional(&client->dev, "pwdn", + GPIOD_OUT_HIGH); ++ ++ ret = ov5647_configure_regulators(dev, sensor); ++ if (ret) { ++ dev_err(dev, "Failed to get power regulators\n"); ++ return ret; ++ } + mutex_init(&sensor->lock); + /* Initialise controls. */ -+ v4l2_ctrl_handler_init(&sensor->ctrls, 9); ++ v4l2_ctrl_handler_init(&sensor->ctrls, 11); + v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, + V4L2_CID_AUTOGAIN, + 0, /* min */ @@ -74253,6 +79254,16 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + sensor->mode->vts_def - + sensor->mode->format.height); + ++ sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ if (sensor->hflip) ++ sensor->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ ++ sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ if (sensor->vflip) ++ sensor->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ + if (sensor->ctrls.error) { + ret = sensor->ctrls.error; + dev_err(&client->dev, "%s control init failed (%d)\n", @@ -74283,10 +79294,16 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 sensor->pad.flags = MEDIA_PAD_FL_SOURCE; sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; -@@ -594,7 +1630,15 @@ static int ov5647_probe(struct i2c_client *client) +@@ -594,9 +1745,23 @@ static int ov5647_probe(struct i2c_client *client) if (ret < 0) goto mutex_remove; ++ ret = regulator_bulk_enable(OV5647_NUM_SUPPLIES, sensor->supplies); ++ if (ret < 0) { ++ dev_err(dev, "Failed to enable regulators\n"); ++ goto error; ++ } ++ + if (sensor->pwdn) { + gpiod_set_value_cansleep(sensor->pwdn, 0); + msleep(PWDN_ACTIVE_DELAY_MS); @@ -74297,9 +79314,17 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 + gpiod_set_value_cansleep(sensor->pwdn, 1); + if (ret < 0) - goto error; +- goto error; ++ goto power_down; + + ret = v4l2_async_register_subdev(sd); + if (ret < 0) +@@ -604,9 +1769,12 @@ static int ov5647_probe(struct i2c_client *client) -@@ -607,6 +1651,7 @@ static int ov5647_probe(struct i2c_client *client) + dev_dbg(dev, "OmniVision OV5647 camera driver probed\n"); + return 0; ++power_down: ++ regulator_bulk_disable(OV5647_NUM_SUPPLIES, sensor->supplies); error: media_entity_cleanup(&sd->entity); mutex_remove: @@ -74307,7 +79332,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 mutex_destroy(&sensor->lock); return ret; } -@@ -618,6 +1663,7 @@ static int ov5647_remove(struct i2c_client *client) +@@ -618,6 +1786,7 @@ static int ov5647_remove(struct i2c_client *client) v4l2_async_unregister_subdev(&ov5647->sd); media_entity_cleanup(&ov5647->sd.entity); @@ -74316,7 +79341,7 @@ index e7d2e5b4ad4b..98a5329d68fb 100644 mutex_destroy(&ov5647->lock); diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c -index 0c10203f822b..2c554626319d 100644 +index 0c10203f822b..f2d77aaed798 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1253,6 +1253,7 @@ static const struct v4l2_subdev_ops ov7251_subdev_ops = { @@ -74327,7 +79352,17 @@ index 0c10203f822b..2c554626319d 100644 struct device *dev = &client->dev; struct fwnode_handle *endpoint; struct ov7251 *ov7251; -@@ -1338,7 +1339,7 @@ static int ov7251_probe(struct i2c_client *client) +@@ -1330,7 +1331,8 @@ static int ov7251_probe(struct i2c_client *client) + return PTR_ERR(ov7251->analog_regulator); + } + +- ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); ++ ov7251->enable_gpio = devm_gpiod_get_optional(dev, "enable", ++ GPIOD_OUT_HIGH); + if (IS_ERR(ov7251->enable_gpio)) { + dev_err(dev, "cannot get enable gpio\n"); + return PTR_ERR(ov7251->enable_gpio); +@@ -1338,7 +1340,7 @@ static int ov7251_probe(struct i2c_client *client) mutex_init(&ov7251->lock); @@ -74336,7 +79371,7 @@ index 0c10203f822b..2c554626319d 100644 ov7251->ctrls.lock = &ov7251->lock; v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops, -@@ -1374,6 +1375,15 @@ static int ov7251_probe(struct i2c_client *client) +@@ -1374,6 +1376,15 @@ static int ov7251_probe(struct i2c_client *client) goto free_ctrl; } @@ -74354,10 +79389,10 @@ index 0c10203f822b..2c554626319d 100644 ov7251->pad.flags = MEDIA_PAD_FL_SOURCE; diff --git a/drivers/media/i2c/ov9281.c b/drivers/media/i2c/ov9281.c new file mode 100644 -index 000000000000..a6ffcdd47b21 +index 000000000000..ff1b99e26a20 --- /dev/null +++ b/drivers/media/i2c/ov9281.c -@@ -0,0 +1,1289 @@ +@@ -0,0 +1,1294 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Omnivision OV9281 1280x800 global shutter image sensor driver @@ -74412,7 +79447,11 @@ index 000000000000..a6ffcdd47b21 +#define OV9281_REG_EXPOSURE 0x3500 +#define OV9281_EXPOSURE_MIN 4 +#define OV9281_EXPOSURE_STEP 1 -+#define OV9281_VTS_MAX 0x7fff ++/* ++ * Number of lines less than frame length (VTS) that exposure must be. ++ * Datasheet states 25, although empirically 5 appears to work. ++ */ ++#define OV9281_EXPOSURE_OFFSET 25 + +#define OV9281_REG_GAIN_H 0x3508 +#define OV9281_REG_GAIN_L 0x3509 @@ -74429,6 +79468,7 @@ index 000000000000..a6ffcdd47b21 +#define OV9281_TEST_PATTERN_DISABLE 0x0 + +#define OV9281_REG_VTS 0x380e ++#define OV9281_VTS_MAX 0x7fff + +/* + * OV9281 native and active pixel array size. @@ -74867,7 +79907,7 @@ index 000000000000..a6ffcdd47b21 + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; -+ fmt->format.colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->format.colorspace = V4L2_COLORSPACE_RAW; + fmt->format.ycbcr_enc = + V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace); + fmt->format.quantization = @@ -74917,7 +79957,7 @@ index 000000000000..a6ffcdd47b21 + fmt->format.height = mode->height; + fmt->format.code = ov9281->code; + fmt->format.field = V4L2_FIELD_NONE; -+ fmt->format.colorspace = V4L2_COLORSPACE_SRGB; ++ fmt->format.colorspace = V4L2_COLORSPACE_RAW; + fmt->format.ycbcr_enc = + V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace); + fmt->format.quantization = @@ -75268,7 +80308,7 @@ index 000000000000..a6ffcdd47b21 + try_fmt->height = def_mode->height; + try_fmt->code = MEDIA_BUS_FMT_Y10_1X10; + try_fmt->field = V4L2_FIELD_NONE; -+ try_fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ try_fmt->colorspace = V4L2_COLORSPACE_RAW; + try_fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(try_fmt->colorspace); + try_fmt->quantization = + V4L2_MAP_QUANTIZATION_DEFAULT(true, try_fmt->colorspace, @@ -75324,7 +80364,7 @@ index 000000000000..a6ffcdd47b21 + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ -+ max = ov9281->cur_mode->height + ctrl->val - 4; ++ max = ov9281->cur_mode->height + ctrl->val - OV9281_EXPOSURE_OFFSET; + __v4l2_ctrl_modify_range(ov9281->exposure, + ov9281->exposure->minimum, max, + ov9281->exposure->step, @@ -75419,7 +80459,7 @@ index 000000000000..a6ffcdd47b21 + OV9281_VTS_MAX - mode->height, 1, + vblank_def); + -+ exposure_max = mode->vts_def - 4; ++ exposure_max = mode->vts_def - OV9281_EXPOSURE_OFFSET; + ov9281->exposure = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops, + V4L2_CID_EXPOSURE, + OV9281_EXPOSURE_MIN, exposure_max, @@ -76010,10 +81050,10 @@ index 000000000000..a98aba03598a +obj-$(CONFIG_VIDEO_BCM2835_UNICAM) += bcm2835-unicam.o diff --git a/drivers/media/platform/bcm2835/bcm2835-unicam.c b/drivers/media/platform/bcm2835/bcm2835-unicam.c new file mode 100644 -index 000000000000..59163f93b207 +index 000000000000..99edc044c934 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c -@@ -0,0 +1,2913 @@ +@@ -0,0 +1,3434 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * BCM283x / BCM271x Unicam Capture Driver @@ -76097,6 +81137,10 @@ index 000000000000..59163f93b207 +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-3"); + ++static int media_controller; ++module_param(media_controller, int, 0644); ++MODULE_PARM_DESC(media_controller, "Use media controller API"); ++ +#define unicam_dbg(level, dev, fmt, arg...) \ + v4l2_dbg(level, debug, &(dev)->v4l2_dev, fmt, ##arg) +#define unicam_info(dev, fmt, arg...) \ @@ -76133,7 +81177,7 @@ index 000000000000..59163f93b207 +#define MIN_WIDTH 16 +#define MIN_HEIGHT 16 +/* Default size of the embedded buffer */ -+#define UNICAM_EMBEDDED_SIZE 8192 ++#define UNICAM_EMBEDDED_SIZE 16384 + +/* + * Size of the dummy buffer. Can be any size really, but the DMA @@ -76147,6 +81191,22 @@ index 000000000000..59163f93b207 + MAX_NODES +}; + ++#define MASK_CS_DEFAULT BIT(V4L2_COLORSPACE_DEFAULT) ++#define MASK_CS_SMPTE170M BIT(V4L2_COLORSPACE_SMPTE170M) ++#define MASK_CS_SMPTE240M BIT(V4L2_COLORSPACE_SMPTE240M) ++#define MASK_CS_REC709 BIT(V4L2_COLORSPACE_REC709) ++#define MASK_CS_BT878 BIT(V4L2_COLORSPACE_BT878) ++#define MASK_CS_470_M BIT(V4L2_COLORSPACE_470_SYSTEM_M) ++#define MASK_CS_470_BG BIT(V4L2_COLORSPACE_470_SYSTEM_BG) ++#define MASK_CS_JPEG BIT(V4L2_COLORSPACE_JPEG) ++#define MASK_CS_SRGB BIT(V4L2_COLORSPACE_SRGB) ++#define MASK_CS_OPRGB BIT(V4L2_COLORSPACE_OPRGB) ++#define MASK_CS_BT2020 BIT(V4L2_COLORSPACE_BT2020) ++#define MASK_CS_RAW BIT(V4L2_COLORSPACE_RAW) ++#define MASK_CS_DCI_P3 BIT(V4L2_COLORSPACE_DCI_P3) ++ ++#define MAX_COLORSPACE 32 ++ +/* + * struct unicam_fmt - Unicam media bus format information + * @pixelformat: V4L2 pixel format FCC identifier. 0 if n/a. @@ -76155,8 +81215,14 @@ index 000000000000..59163f93b207 + * @code: V4L2 media bus format code. + * @depth: Bits per pixel as delivered from the source. + * @csi_dt: CSI data type. ++ * @valid_colorspaces: Bitmask of valid colorspaces so that the Media Controller ++ * centric try_fmt can validate the colorspace and pass ++ * v4l2-compliance. + * @check_variants: Flag to denote that there are multiple mediabus formats + * still in the list that could match this V4L2 format. ++ * @mc_skip: Media Controller shouldn't list this format via ENUM_FMT as it is ++ * a duplicate of an earlier format. ++ * @metadata_fmt: This format only applies to the metadata pad. + */ +struct unicam_fmt { + u32 fourcc; @@ -76164,7 +81230,10 @@ index 000000000000..59163f93b207 + u32 code; + u8 depth; + u8 csi_dt; -+ u8 check_variants; ++ u32 valid_colorspaces; ++ u8 check_variants:1; ++ u8 mc_skip:1; ++ u8 metadata_fmt:1; +}; + +static const struct unicam_fmt formats[] = { @@ -76175,173 +81244,216 @@ index 000000000000..59163f93b207 + .depth = 16, + .csi_dt = 0x1e, + .check_variants = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .depth = 16, + .csi_dt = 0x1e, + .check_variants = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .code = MEDIA_BUS_FMT_YVYU8_2X8, + .depth = 16, + .csi_dt = 0x1e, + .check_variants = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .depth = 16, + .csi_dt = 0x1e, + .check_variants = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .code = MEDIA_BUS_FMT_YUYV8_1X16, + .depth = 16, + .csi_dt = 0x1e, ++ .mc_skip = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .code = MEDIA_BUS_FMT_UYVY8_1X16, + .depth = 16, + .csi_dt = 0x1e, ++ .mc_skip = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .code = MEDIA_BUS_FMT_YVYU8_1X16, + .depth = 16, + .csi_dt = 0x1e, ++ .mc_skip = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .code = MEDIA_BUS_FMT_VYUY8_1X16, + .depth = 16, + .csi_dt = 0x1e, ++ .mc_skip = 1, ++ .valid_colorspaces = MASK_CS_SMPTE170M | MASK_CS_REC709 | ++ MASK_CS_JPEG, + }, { + /* RGB Formats */ + .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ + .code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .depth = 16, + .csi_dt = 0x22, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB565_2X8_BE, + .depth = 16, -+ .csi_dt = 0x22 ++ .csi_dt = 0x22, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .depth = 16, + .csi_dt = 0x21, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, + .depth = 16, + .csi_dt = 0x21, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ + .code = MEDIA_BUS_FMT_RGB888_1X24, + .depth = 24, + .csi_dt = 0x24, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ + .code = MEDIA_BUS_FMT_BGR888_1X24, + .depth = 24, + .csi_dt = 0x24, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ + .code = MEDIA_BUS_FMT_ARGB8888_1X32, + .depth = 32, + .csi_dt = 0x0, ++ .valid_colorspaces = MASK_CS_SRGB, + }, { + /* Bayer Formats */ + .fourcc = V4L2_PIX_FMT_SBGGR8, + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR10P, + .repacked_fourcc = V4L2_PIX_FMT_SBGGR10, + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .depth = 10, + .csi_dt = 0x2b, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG10P, + .repacked_fourcc = V4L2_PIX_FMT_SGBRG10, + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .depth = 10, + .csi_dt = 0x2b, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG10P, + .repacked_fourcc = V4L2_PIX_FMT_SGRBG10, + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .depth = 10, + .csi_dt = 0x2b, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB10P, + .repacked_fourcc = V4L2_PIX_FMT_SRGGB10, + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .depth = 10, + .csi_dt = 0x2b, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR12P, + .repacked_fourcc = V4L2_PIX_FMT_SBGGR12, + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .depth = 12, + .csi_dt = 0x2c, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG12P, + .repacked_fourcc = V4L2_PIX_FMT_SGBRG12, + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .depth = 12, + .csi_dt = 0x2c, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG12P, + .repacked_fourcc = V4L2_PIX_FMT_SGRBG12, + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .depth = 12, + .csi_dt = 0x2c, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB12P, + .repacked_fourcc = V4L2_PIX_FMT_SRGGB12, + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .depth = 12, + .csi_dt = 0x2c, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR14P, + .repacked_fourcc = V4L2_PIX_FMT_SBGGR14, + .code = MEDIA_BUS_FMT_SBGGR14_1X14, + .depth = 14, + .csi_dt = 0x2d, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG14P, + .repacked_fourcc = V4L2_PIX_FMT_SGBRG14, + .code = MEDIA_BUS_FMT_SGBRG14_1X14, + .depth = 14, + .csi_dt = 0x2d, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG14P, + .repacked_fourcc = V4L2_PIX_FMT_SGRBG14, + .code = MEDIA_BUS_FMT_SGRBG14_1X14, + .depth = 14, + .csi_dt = 0x2d, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB14P, + .repacked_fourcc = V4L2_PIX_FMT_SRGGB14, + .code = MEDIA_BUS_FMT_SRGGB14_1X14, + .depth = 14, + .csi_dt = 0x2d, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + /* + * 16 bit Bayer formats could be supported, but there is no CSI2 @@ -76354,30 +81466,35 @@ index 000000000000..59163f93b207 + .code = MEDIA_BUS_FMT_Y8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_Y10P, + .repacked_fourcc = V4L2_PIX_FMT_Y10, + .code = MEDIA_BUS_FMT_Y10_1X10, + .depth = 10, + .csi_dt = 0x2b, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_Y12P, + .repacked_fourcc = V4L2_PIX_FMT_Y12, + .code = MEDIA_BUS_FMT_Y12_1X12, + .depth = 12, + .csi_dt = 0x2c, ++ .valid_colorspaces = MASK_CS_RAW, + }, { + .fourcc = V4L2_PIX_FMT_Y14P, + .repacked_fourcc = V4L2_PIX_FMT_Y14, + .code = MEDIA_BUS_FMT_Y14_1X14, + .depth = 14, + .csi_dt = 0x2d, ++ .valid_colorspaces = MASK_CS_RAW, + }, + /* Embedded data format */ + { + .fourcc = V4L2_META_FMT_SENSOR_DATA, + .code = MEDIA_BUS_FMT_SENSOR_DATA, + .depth = 8, ++ .metadata_fmt = 1, + } +}; + @@ -76396,6 +81513,8 @@ index 000000000000..59163f93b207 + int open; + bool streaming; + unsigned int pad_id; ++ /* Source pad id on the sensor for this node */ ++ unsigned int src_pad_id; + /* Pointer pointing to current v4l2_buffer */ + struct unicam_buffer *cur_frm; + /* Pointer pointing to next v4l2_buffer */ @@ -76420,6 +81539,7 @@ index 000000000000..59163f93b207 + struct unicam_device *dev; + struct media_pad pad; + unsigned int embedded_lines; ++ struct media_pipeline pipe; + /* + * Dummy buffer intended to be used by unicam + * if we have no other queued buffers to swap to. @@ -76473,6 +81593,8 @@ index 000000000000..59163f93b207 + + struct unicam_node node[MAX_NODES]; + struct v4l2_ctrl_handler ctrl_handler; ++ ++ bool mc_api; +}; + +static inline struct unicam_device * @@ -76606,7 +81728,7 @@ index 000000000000..59163f93b207 +{ + struct v4l2_subdev_format sd_fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, -+ .pad = pad_id ++ .pad = dev->node[pad_id].src_pad_id, + }; + int ret; + @@ -76628,7 +81750,7 @@ index 000000000000..59163f93b207 +{ + struct v4l2_subdev_format sd_fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, -+ .pad = pad_id ++ .pad = dev->node[pad_id].src_pad_id, + }; + int ret; + @@ -76885,6 +82007,9 @@ index 000000000000..59163f93b207 + if (unicam->node[i].cur_frm) + unicam->node[i].cur_frm->vb.vb2_buf.timestamp = + ts; ++ else ++ unicam_dbg(2, unicam, "ISR: [%d] Dropping frame, buffer not available at FS\n", ++ i); + /* + * Set the next frame output to go to a dummy frame + * if we have not managed to obtain another frame @@ -76914,14 +82039,10 @@ index 000000000000..59163f93b207 + } + } + -+ if (reg_read(unicam, UNICAM_ICTL) & UNICAM_FCM) { -+ /* Switch out of trigger mode if selected */ -+ reg_write_field(unicam, UNICAM_ICTL, 1, UNICAM_TFC); -+ reg_write_field(unicam, UNICAM_ICTL, 0, UNICAM_FCM); -+ } + return IRQ_HANDLED; +} + ++/* V4L2 Common IOCTLs */ +static int unicam_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ @@ -76939,6 +82060,38 @@ index 000000000000..59163f93b207 + return 0; +} + ++static int unicam_log_status(struct file *file, void *fh) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ u32 reg; ++ ++ /* status for sub devices */ ++ v4l2_device_call_all(&dev->v4l2_dev, 0, core, log_status); ++ ++ unicam_info(dev, "-----Receiver status-----\n"); ++ unicam_info(dev, "V4L2 width/height: %ux%u\n", ++ node->v_fmt.fmt.pix.width, node->v_fmt.fmt.pix.height); ++ unicam_info(dev, "Mediabus format: %08x\n", node->fmt->code); ++ unicam_info(dev, "V4L2 format: %08x\n", ++ node->v_fmt.fmt.pix.pixelformat); ++ reg = reg_read(dev, UNICAM_IPIPE); ++ unicam_info(dev, "Unpacking/packing: %u / %u\n", ++ get_field(reg, UNICAM_PUM_MASK), ++ get_field(reg, UNICAM_PPM_MASK)); ++ unicam_info(dev, "----Live data----\n"); ++ unicam_info(dev, "Programmed stride: %4u\n", ++ reg_read(dev, UNICAM_IBLS)); ++ unicam_info(dev, "Detected resolution: %ux%u\n", ++ reg_read(dev, UNICAM_IHSTA), ++ reg_read(dev, UNICAM_IVSTA)); ++ unicam_info(dev, "Write pointer: %08x\n", ++ reg_read(dev, UNICAM_IBWP)); ++ ++ return 0; ++} ++ ++/* V4L2 Video Centric IOCTLs */ +static int unicam_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ @@ -77283,6 +82436,727 @@ index 000000000000..59163f93b207 + return 0; +} + ++static int unicam_enum_input(struct file *file, void *priv, ++ struct v4l2_input *inp) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ int ret; ++ ++ if (inp->index != 0) ++ return -EINVAL; ++ ++ inp->type = V4L2_INPUT_TYPE_CAMERA; ++ if (v4l2_subdev_has_op(dev->sensor, video, s_dv_timings)) { ++ inp->capabilities = V4L2_IN_CAP_DV_TIMINGS; ++ inp->std = 0; ++ } else if (v4l2_subdev_has_op(dev->sensor, video, s_std)) { ++ inp->capabilities = V4L2_IN_CAP_STD; ++ if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std) < 0) ++ inp->std = V4L2_STD_ALL; ++ } else { ++ inp->capabilities = 0; ++ inp->std = 0; ++ } ++ ++ if (v4l2_subdev_has_op(dev->sensor, video, g_input_status)) { ++ ret = v4l2_subdev_call(dev->sensor, video, g_input_status, ++ &inp->status); ++ if (ret < 0) ++ return ret; ++ } ++ ++ snprintf(inp->name, sizeof(inp->name), "Camera 0"); ++ return 0; ++} ++ ++static int unicam_g_input(struct file *file, void *priv, unsigned int *i) ++{ ++ *i = 0; ++ ++ return 0; ++} ++ ++static int unicam_s_input(struct file *file, void *priv, unsigned int i) ++{ ++ /* ++ * FIXME: Ideally we would like to be able to query the source ++ * subdevice for information over the input connectors it supports, ++ * and map that through in to a call to video_ops->s_routing. ++ * There is no infrastructure support for defining that within ++ * devicetree at present. Until that is implemented we can't ++ * map a user physical connector number to s_routing input number. ++ */ ++ if (i > 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int unicam_querystd(struct file *file, void *priv, ++ v4l2_std_id *std) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_subdev_call(dev->sensor, video, querystd, std); ++} ++ ++static int unicam_g_std(struct file *file, void *priv, v4l2_std_id *std) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_subdev_call(dev->sensor, video, g_std, std); ++} ++ ++static int unicam_s_std(struct file *file, void *priv, v4l2_std_id std) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ int ret; ++ v4l2_std_id current_std; ++ ++ ret = v4l2_subdev_call(dev->sensor, video, g_std, ¤t_std); ++ if (ret) ++ return ret; ++ ++ if (std == current_std) ++ return 0; ++ ++ if (vb2_is_busy(&node->buffer_queue)) ++ return -EBUSY; ++ ++ ret = v4l2_subdev_call(dev->sensor, video, s_std, std); ++ ++ /* Force recomputation of bytesperline */ ++ node->v_fmt.fmt.pix.bytesperline = 0; ++ ++ unicam_reset_format(node); ++ ++ return ret; ++} ++ ++static int unicam_s_edid(struct file *file, void *priv, struct v4l2_edid *edid) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_subdev_call(dev->sensor, pad, set_edid, edid); ++} ++ ++static int unicam_g_edid(struct file *file, void *priv, struct v4l2_edid *edid) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_subdev_call(dev->sensor, pad, get_edid, edid); ++} ++ ++static int unicam_s_selection(struct file *file, void *priv, ++ struct v4l2_selection *sel) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ struct v4l2_subdev_selection sdsel = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .target = sel->target, ++ .flags = sel->flags, ++ .r = sel->r, ++ }; ++ ++ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ return v4l2_subdev_call(dev->sensor, pad, set_selection, NULL, &sdsel); ++} ++ ++static int unicam_g_selection(struct file *file, void *priv, ++ struct v4l2_selection *sel) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ struct v4l2_subdev_selection sdsel = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .target = sel->target, ++ }; ++ int ret; ++ ++ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ ret = v4l2_subdev_call(dev->sensor, pad, get_selection, NULL, &sdsel); ++ if (!ret) ++ sel->r = sdsel.r; ++ ++ return ret; ++} ++ ++static int unicam_enum_framesizes(struct file *file, void *priv, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ const struct unicam_fmt *fmt; ++ struct v4l2_subdev_frame_size_enum fse; ++ int ret; ++ ++ /* check for valid format */ ++ fmt = find_format_by_pix(dev, fsize->pixel_format); ++ if (!fmt) { ++ unicam_dbg(3, dev, "Invalid pixel code: %x\n", ++ fsize->pixel_format); ++ return -EINVAL; ++ } ++ fse.code = fmt->code; ++ ++ fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; ++ fse.index = fsize->index; ++ fse.pad = node->src_pad_id; ++ ++ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse); ++ if (ret) ++ return ret; ++ ++ unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n", ++ __func__, fse.index, fse.code, fse.min_width, fse.max_width, ++ fse.min_height, fse.max_height); ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; ++ fsize->discrete.width = fse.max_width; ++ fsize->discrete.height = fse.max_height; ++ ++ return 0; ++} ++ ++static int unicam_enum_frameintervals(struct file *file, void *priv, ++ struct v4l2_frmivalenum *fival) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ const struct unicam_fmt *fmt; ++ struct v4l2_subdev_frame_interval_enum fie = { ++ .index = fival->index, ++ .pad = node->src_pad_id, ++ .width = fival->width, ++ .height = fival->height, ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ int ret; ++ ++ fmt = find_format_by_pix(dev, fival->pixel_format); ++ if (!fmt) ++ return -EINVAL; ++ ++ fie.code = fmt->code; ++ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval, ++ NULL, &fie); ++ if (ret) ++ return ret; ++ ++ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ fival->discrete = fie.interval; ++ ++ return 0; ++} ++ ++static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a); ++} ++ ++static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a); ++} ++ ++static int unicam_g_dv_timings(struct file *file, void *priv, ++ struct v4l2_dv_timings *timings) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_subdev_call(dev->sensor, video, g_dv_timings, timings); ++} ++ ++static int unicam_s_dv_timings(struct file *file, void *priv, ++ struct v4l2_dv_timings *timings) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ struct v4l2_dv_timings current_timings; ++ int ret; ++ ++ ret = v4l2_subdev_call(dev->sensor, video, g_dv_timings, ++ ¤t_timings); ++ ++ if (ret < 0) ++ return ret; ++ ++ if (v4l2_match_dv_timings(timings, ¤t_timings, 0, false)) ++ return 0; ++ ++ if (vb2_is_busy(&node->buffer_queue)) ++ return -EBUSY; ++ ++ ret = v4l2_subdev_call(dev->sensor, video, s_dv_timings, timings); ++ ++ /* Force recomputation of bytesperline */ ++ node->v_fmt.fmt.pix.bytesperline = 0; ++ ++ unicam_reset_format(node); ++ ++ return ret; ++} ++ ++static int unicam_query_dv_timings(struct file *file, void *priv, ++ struct v4l2_dv_timings *timings) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ return v4l2_subdev_call(dev->sensor, video, query_dv_timings, timings); ++} ++ ++static int unicam_enum_dv_timings(struct file *file, void *priv, ++ struct v4l2_enum_dv_timings *timings) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ int ret; ++ ++ timings->pad = node->src_pad_id; ++ ret = v4l2_subdev_call(dev->sensor, pad, enum_dv_timings, timings); ++ timings->pad = node->pad_id; ++ ++ return ret; ++} ++ ++static int unicam_dv_timings_cap(struct file *file, void *priv, ++ struct v4l2_dv_timings_cap *cap) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ int ret; ++ ++ cap->pad = node->src_pad_id; ++ ret = v4l2_subdev_call(dev->sensor, pad, dv_timings_cap, cap); ++ cap->pad = node->pad_id; ++ ++ return ret; ++} ++ ++static int unicam_subscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ switch (sub->type) { ++ case V4L2_EVENT_FRAME_SYNC: ++ return v4l2_event_subscribe(fh, sub, 2, NULL); ++ case V4L2_EVENT_SOURCE_CHANGE: ++ return v4l2_event_subscribe(fh, sub, 4, NULL); ++ } ++ ++ return v4l2_ctrl_subscribe_event(fh, sub); ++} ++ ++static void unicam_notify(struct v4l2_subdev *sd, ++ unsigned int notification, void *arg) ++{ ++ struct unicam_device *dev = to_unicam_device(sd->v4l2_dev); ++ ++ switch (notification) { ++ case V4L2_DEVICE_NOTIFY_EVENT: ++ v4l2_event_queue(&dev->node[IMAGE_PAD].video_dev, arg); ++ break; ++ default: ++ break; ++ } ++} ++ ++/* unicam capture ioctl operations */ ++static const struct v4l2_ioctl_ops unicam_ioctl_ops = { ++ .vidioc_querycap = unicam_querycap, ++ .vidioc_enum_fmt_vid_cap = unicam_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = unicam_g_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = unicam_s_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = unicam_try_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_meta_cap = unicam_enum_fmt_meta_cap, ++ .vidioc_g_fmt_meta_cap = unicam_g_fmt_meta_cap, ++ .vidioc_s_fmt_meta_cap = unicam_g_fmt_meta_cap, ++ .vidioc_try_fmt_meta_cap = unicam_g_fmt_meta_cap, ++ ++ .vidioc_enum_input = unicam_enum_input, ++ .vidioc_g_input = unicam_g_input, ++ .vidioc_s_input = unicam_s_input, ++ ++ .vidioc_querystd = unicam_querystd, ++ .vidioc_s_std = unicam_s_std, ++ .vidioc_g_std = unicam_g_std, ++ ++ .vidioc_g_edid = unicam_g_edid, ++ .vidioc_s_edid = unicam_s_edid, ++ ++ .vidioc_enum_framesizes = unicam_enum_framesizes, ++ .vidioc_enum_frameintervals = unicam_enum_frameintervals, ++ ++ .vidioc_g_selection = unicam_g_selection, ++ .vidioc_s_selection = unicam_s_selection, ++ ++ .vidioc_g_parm = unicam_g_parm, ++ .vidioc_s_parm = unicam_s_parm, ++ ++ .vidioc_s_dv_timings = unicam_s_dv_timings, ++ .vidioc_g_dv_timings = unicam_g_dv_timings, ++ .vidioc_query_dv_timings = unicam_query_dv_timings, ++ .vidioc_enum_dv_timings = unicam_enum_dv_timings, ++ .vidioc_dv_timings_cap = unicam_dv_timings_cap, ++ ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++ ++ .vidioc_log_status = unicam_log_status, ++ .vidioc_subscribe_event = unicam_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++/* V4L2 Media Controller Centric IOCTLs */ ++ ++static int unicam_mc_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ int i, j; ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) { ++ if (f->mbus_code && formats[i].code != f->mbus_code) ++ continue; ++ if (formats[i].mc_skip || formats[i].metadata_fmt) ++ continue; ++ ++ if (formats[i].fourcc) { ++ if (j == f->index) { ++ f->pixelformat = formats[i].fourcc; ++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ return 0; ++ } ++ j++; ++ } ++ if (formats[i].repacked_fourcc) { ++ if (j == f->index) { ++ f->pixelformat = formats[i].repacked_fourcc; ++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ return 0; ++ } ++ j++; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static int unicam_mc_g_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ ++ if (node->pad_id != IMAGE_PAD) ++ return -EINVAL; ++ ++ *f = node->v_fmt; ++ ++ return 0; ++} ++ ++static void unicam_mc_try_fmt(struct unicam_node *node, struct v4l2_format *f, ++ const struct unicam_fmt **ret_fmt) ++{ ++ struct v4l2_pix_format *v4l2_format = &f->fmt.pix; ++ struct unicam_device *dev = node->dev; ++ const struct unicam_fmt *fmt; ++ int is_rgb; ++ ++ /* ++ * Default to the first format if the requested pixel format code isn't ++ * supported. ++ */ ++ fmt = find_format_by_pix(dev, v4l2_format->pixelformat); ++ if (!fmt) { ++ fmt = &formats[0]; ++ v4l2_format->pixelformat = fmt->fourcc; ++ } ++ ++ unicam_calc_format_size_bpl(dev, fmt, f); ++ ++ if (v4l2_format->field == V4L2_FIELD_ANY) ++ v4l2_format->field = V4L2_FIELD_NONE; ++ ++ if (ret_fmt) ++ *ret_fmt = fmt; ++ ++ if (v4l2_format->colorspace >= MAX_COLORSPACE || ++ !(fmt->valid_colorspaces & (1 << v4l2_format->colorspace))) { ++ v4l2_format->colorspace = __ffs(fmt->valid_colorspaces); ++ ++ v4l2_format->xfer_func = ++ V4L2_MAP_XFER_FUNC_DEFAULT(v4l2_format->colorspace); ++ v4l2_format->ycbcr_enc = ++ V4L2_MAP_YCBCR_ENC_DEFAULT(v4l2_format->colorspace); ++ is_rgb = v4l2_format->colorspace == V4L2_COLORSPACE_SRGB; ++ v4l2_format->quantization = ++ V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, ++ v4l2_format->colorspace, ++ v4l2_format->ycbcr_enc); ++ } ++ ++ unicam_dbg(3, dev, "%s: %08x %ux%u (bytesperline %u sizeimage %u)\n", ++ __func__, v4l2_format->pixelformat, ++ v4l2_format->width, v4l2_format->height, ++ v4l2_format->bytesperline, v4l2_format->sizeimage); ++} ++ ++static int unicam_mc_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ ++ unicam_mc_try_fmt(node, f, NULL); ++ return 0; ++} ++ ++static int unicam_mc_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ const struct unicam_fmt *fmt; ++ ++ if (vb2_is_busy(&node->buffer_queue)) { ++ unicam_dbg(3, dev, "%s device busy\n", __func__); ++ return -EBUSY; ++ } ++ ++ unicam_mc_try_fmt(node, f, &fmt); ++ ++ node->v_fmt = *f; ++ node->fmt = fmt; ++ ++ return 0; ++} ++ ++static int unicam_mc_enum_framesizes(struct file *file, void *fh, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ struct unicam_device *dev = node->dev; ++ ++ if (fsize->index > 0) ++ return -EINVAL; ++ ++ if (!find_format_by_pix(dev, fsize->pixel_format)) { ++ unicam_dbg(3, dev, "Invalid pixel format 0x%08x\n", ++ fsize->pixel_format); ++ return -EINVAL; ++ } ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = MIN_WIDTH; ++ fsize->stepwise.max_width = MAX_WIDTH; ++ fsize->stepwise.step_width = 1; ++ fsize->stepwise.min_height = MIN_HEIGHT; ++ fsize->stepwise.max_height = MAX_HEIGHT; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int unicam_mc_enum_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ int i, j; ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) { ++ if (f->mbus_code && formats[i].code != f->mbus_code) ++ continue; ++ if (!formats[i].metadata_fmt) ++ continue; ++ ++ if (formats[i].fourcc) { ++ if (j == f->index) { ++ f->pixelformat = formats[i].fourcc; ++ f->type = V4L2_BUF_TYPE_META_CAPTURE; ++ return 0; ++ } ++ j++; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static int unicam_mc_g_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ ++ if (node->pad_id != METADATA_PAD) ++ return -EINVAL; ++ ++ *f = node->v_fmt; ++ ++ return 0; ++} ++ ++static int unicam_mc_try_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ ++ if (node->pad_id != METADATA_PAD) ++ return -EINVAL; ++ ++ f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA; ++ ++ return 0; ++} ++ ++static int unicam_mc_s_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct unicam_node *node = video_drvdata(file); ++ ++ if (node->pad_id != METADATA_PAD) ++ return -EINVAL; ++ ++ unicam_mc_try_fmt_meta_cap(file, priv, f); ++ ++ node->v_fmt = *f; ++ ++ return 0; ++} ++ ++static const struct v4l2_ioctl_ops unicam_mc_ioctl_ops = { ++ .vidioc_querycap = unicam_querycap, ++ .vidioc_enum_fmt_vid_cap = unicam_mc_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = unicam_mc_g_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = unicam_mc_try_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = unicam_mc_s_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_meta_cap = unicam_mc_enum_fmt_meta_cap, ++ .vidioc_g_fmt_meta_cap = unicam_mc_g_fmt_meta_cap, ++ .vidioc_try_fmt_meta_cap = unicam_mc_try_fmt_meta_cap, ++ .vidioc_s_fmt_meta_cap = unicam_mc_s_fmt_meta_cap, ++ ++ .vidioc_enum_framesizes = unicam_mc_enum_framesizes, ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++ ++ .vidioc_log_status = unicam_log_status, ++ .vidioc_subscribe_event = unicam_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static int ++unicam_mc_subdev_link_validate_get_format(struct media_pad *pad, ++ struct v4l2_subdev_format *fmt) ++{ ++ if (is_media_entity_v4l2_subdev(pad->entity)) { ++ struct v4l2_subdev *sd = ++ media_entity_to_v4l2_subdev(pad->entity); ++ ++ fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; ++ fmt->pad = pad->index; ++ return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); ++ } ++ ++ return -EINVAL; ++} ++ ++static int unicam_mc_video_link_validate(struct media_link *link) ++{ ++ struct video_device *vd = container_of(link->sink->entity, ++ struct video_device, entity); ++ struct unicam_node *node = container_of(vd, struct unicam_node, ++ video_dev); ++ struct unicam_device *unicam = node->dev; ++ struct v4l2_subdev_format source_fmt; ++ int ret; ++ ++ if (!media_entity_remote_pad(link->sink->entity->pads)) { ++ unicam_dbg(1, unicam, ++ "video node %s pad not connected\n", vd->name); ++ return -ENOTCONN; ++ } ++ ++ ret = unicam_mc_subdev_link_validate_get_format(link->source, ++ &source_fmt); ++ if (ret < 0) ++ return 0; ++ ++ if (node->pad_id == IMAGE_PAD) { ++ struct v4l2_pix_format *pix_fmt = &node->v_fmt.fmt.pix; ++ const struct unicam_fmt *fmt; ++ ++ if (source_fmt.format.width != pix_fmt->width || ++ source_fmt.format.height != pix_fmt->height) { ++ unicam_err(unicam, ++ "Wrong width or height %ux%u (remote pad set to %ux%u)\n", ++ pix_fmt->width, pix_fmt->height, ++ source_fmt.format.width, ++ source_fmt.format.height); ++ return -EINVAL; ++ } ++ ++ fmt = find_format_by_code(source_fmt.format.code); ++ ++ if (!fmt || (fmt->fourcc != pix_fmt->pixelformat && ++ fmt->repacked_fourcc != pix_fmt->pixelformat)) ++ return -EINVAL; ++ } else { ++ struct v4l2_meta_format *meta_fmt = &node->v_fmt.fmt.meta; ++ ++ if (source_fmt.format.width != meta_fmt->buffersize || ++ source_fmt.format.height != 1 || ++ source_fmt.format.code != MEDIA_BUS_FMT_SENSOR_DATA) { ++ unicam_err(unicam, ++ "Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n", ++ meta_fmt->buffersize, 1, ++ MEDIA_BUS_FMT_SENSOR_DATA, ++ source_fmt.format.width, ++ source_fmt.format.height, ++ source_fmt.format.code); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct media_entity_operations unicam_mc_entity_ops = { ++ .link_validate = unicam_mc_video_link_validate, ++}; ++ ++/* videobuf2 Operations */ ++ +static int unicam_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, + unsigned int *nplanes, @@ -77474,8 +83348,7 @@ index 000000000000..59163f93b207 + + reg_write_field(dev, UNICAM_ANA, 0, UNICAM_DDL); + -+ /* Always start in trigger frame capture mode (UNICAM_FCM set) */ -+ val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_FCM | UNICAM_IBOB; ++ val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_IBOB; + set_field(&val, line_int_freq, UNICAM_LCIE_MASK); + reg_write(dev, UNICAM_ICTL, val); + reg_write(dev, UNICAM_STA, UNICAM_STA_MASK_ALL); @@ -77588,12 +83461,6 @@ index 000000000000..59163f93b207 + /* Load embedded data buffer pointers if needed */ + if (dev->node[METADATA_PAD].streaming && dev->sensor_embedded_data) + reg_write_field(dev, UNICAM_DCS, 1, UNICAM_LDP); -+ -+ /* -+ * Enable trigger only for the first frame to -+ * sync correctly to the FS from the source. -+ */ -+ reg_write_field(dev, UNICAM_ICTL, 1, UNICAM_TFC); +} + +static void unicam_disable(struct unicam_device *dev) @@ -77680,6 +83547,12 @@ index 000000000000..59163f93b207 + goto err_streaming; + } + ++ ret = media_pipeline_start(&node->video_dev.entity, &node->pipe); ++ if (ret < 0) { ++ unicam_err(dev, "Failed to start media pipeline: %d\n", ret); ++ goto err_pm_put; ++ } ++ + dev->active_data_lanes = dev->max_data_lanes; + + if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) { @@ -77689,7 +83562,7 @@ index 000000000000..59163f93b207 + 0, &mbus_config); + if (ret < 0 && ret != -ENOIOCTLCMD) { + unicam_dbg(3, dev, "g_mbus_config failed\n"); -+ goto err_pm_put; ++ goto error_pipeline; + } + + dev->active_data_lanes = @@ -77702,7 +83575,7 @@ index 000000000000..59163f93b207 + dev->active_data_lanes, + dev->max_data_lanes); + ret = -EINVAL; -+ goto err_pm_put; ++ goto error_pipeline; + } + } + @@ -77712,13 +83585,13 @@ index 000000000000..59163f93b207 + dev->vpu_req = clk_request_start(dev->vpu_clock, MIN_VPU_CLOCK_RATE); + if (!dev->vpu_req) { + unicam_err(dev, "failed to set up VPU clock\n"); -+ goto err_pm_put; ++ goto error_pipeline; + } + + ret = clk_prepare_enable(dev->vpu_clock); + if (ret) { + unicam_err(dev, "Failed to enable VPU clock: %d\n", ret); -+ goto err_pm_put; ++ goto error_pipeline; + } + + ret = clk_set_rate(dev->clock, 100 * 1000 * 1000); @@ -77768,6 +83641,8 @@ index 000000000000..59163f93b207 +err_vpu_clock: + clk_request_done(dev->vpu_req); + clk_disable_unprepare(dev->vpu_clock); ++error_pipeline: ++ media_pipeline_stop(&node->video_dev.entity); +err_pm_put: + unicam_runtime_put(dev); +err_streaming: @@ -77795,6 +83670,8 @@ index 000000000000..59163f93b207 + + unicam_disable(dev); + ++ media_pipeline_stop(&node->video_dev.entity); ++ + if (dev->clocks_enabled) { + clk_request_done(dev->vpu_req); + clk_disable_unprepare(dev->vpu_clock); @@ -77817,368 +83694,6 @@ index 000000000000..59163f93b207 + unicam_return_buffers(node, VB2_BUF_STATE_ERROR); +} + -+static int unicam_enum_input(struct file *file, void *priv, -+ struct v4l2_input *inp) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ int ret; -+ -+ if (inp->index != 0) -+ return -EINVAL; -+ -+ inp->type = V4L2_INPUT_TYPE_CAMERA; -+ if (v4l2_subdev_has_op(dev->sensor, video, s_dv_timings)) { -+ inp->capabilities = V4L2_IN_CAP_DV_TIMINGS; -+ inp->std = 0; -+ } else if (v4l2_subdev_has_op(dev->sensor, video, s_std)) { -+ inp->capabilities = V4L2_IN_CAP_STD; -+ if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std) < 0) -+ inp->std = V4L2_STD_ALL; -+ } else { -+ inp->capabilities = 0; -+ inp->std = 0; -+ } -+ -+ if (v4l2_subdev_has_op(dev->sensor, video, g_input_status)) { -+ ret = v4l2_subdev_call(dev->sensor, video, g_input_status, -+ &inp->status); -+ if (ret < 0) -+ return ret; -+ } -+ -+ snprintf(inp->name, sizeof(inp->name), "Camera 0"); -+ return 0; -+} -+ -+static int unicam_g_input(struct file *file, void *priv, unsigned int *i) -+{ -+ *i = 0; -+ -+ return 0; -+} -+ -+static int unicam_s_input(struct file *file, void *priv, unsigned int i) -+{ -+ /* -+ * FIXME: Ideally we would like to be able to query the source -+ * subdevice for information over the input connectors it supports, -+ * and map that through in to a call to video_ops->s_routing. -+ * There is no infrastructure support for defining that within -+ * devicetree at present. Until that is implemented we can't -+ * map a user physical connector number to s_routing input number. -+ */ -+ if (i > 0) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int unicam_querystd(struct file *file, void *priv, -+ v4l2_std_id *std) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, video, querystd, std); -+} -+ -+static int unicam_g_std(struct file *file, void *priv, v4l2_std_id *std) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, video, g_std, std); -+} -+ -+static int unicam_s_std(struct file *file, void *priv, v4l2_std_id std) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ int ret; -+ v4l2_std_id current_std; -+ -+ ret = v4l2_subdev_call(dev->sensor, video, g_std, ¤t_std); -+ if (ret) -+ return ret; -+ -+ if (std == current_std) -+ return 0; -+ -+ if (vb2_is_busy(&node->buffer_queue)) -+ return -EBUSY; -+ -+ ret = v4l2_subdev_call(dev->sensor, video, s_std, std); -+ -+ /* Force recomputation of bytesperline */ -+ node->v_fmt.fmt.pix.bytesperline = 0; -+ -+ unicam_reset_format(node); -+ -+ return ret; -+} -+ -+static int unicam_s_edid(struct file *file, void *priv, struct v4l2_edid *edid) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, pad, set_edid, edid); -+} -+ -+static int unicam_g_edid(struct file *file, void *priv, struct v4l2_edid *edid) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, pad, get_edid, edid); -+} -+ -+static int unicam_s_selection(struct file *file, void *priv, -+ struct v4l2_selection *sel) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ struct v4l2_subdev_selection sdsel = { -+ .which = V4L2_SUBDEV_FORMAT_ACTIVE, -+ .target = sel->target, -+ .flags = sel->flags, -+ .r = sel->r, -+ }; -+ -+ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ return v4l2_subdev_call(dev->sensor, pad, set_selection, NULL, &sdsel); -+} -+ -+static int unicam_g_selection(struct file *file, void *priv, -+ struct v4l2_selection *sel) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ struct v4l2_subdev_selection sdsel = { -+ .which = V4L2_SUBDEV_FORMAT_ACTIVE, -+ .target = sel->target, -+ }; -+ int ret; -+ -+ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ ret = v4l2_subdev_call(dev->sensor, pad, get_selection, NULL, &sdsel); -+ if (!ret) -+ sel->r = sdsel.r; -+ -+ return ret; -+} -+ -+static int unicam_enum_framesizes(struct file *file, void *priv, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ const struct unicam_fmt *fmt; -+ struct v4l2_subdev_frame_size_enum fse; -+ int ret; -+ -+ /* check for valid format */ -+ fmt = find_format_by_pix(dev, fsize->pixel_format); -+ if (!fmt) { -+ unicam_dbg(3, dev, "Invalid pixel code: %x\n", -+ fsize->pixel_format); -+ return -EINVAL; -+ } -+ fse.code = fmt->code; -+ -+ fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; -+ fse.index = fsize->index; -+ fse.pad = node->pad_id; -+ -+ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_size, NULL, &fse); -+ if (ret) -+ return ret; -+ -+ unicam_dbg(1, dev, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n", -+ __func__, fse.index, fse.code, fse.min_width, fse.max_width, -+ fse.min_height, fse.max_height); -+ -+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; -+ fsize->discrete.width = fse.max_width; -+ fsize->discrete.height = fse.max_height; -+ -+ return 0; -+} -+ -+static int unicam_enum_frameintervals(struct file *file, void *priv, -+ struct v4l2_frmivalenum *fival) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ const struct unicam_fmt *fmt; -+ struct v4l2_subdev_frame_interval_enum fie = { -+ .index = fival->index, -+ .width = fival->width, -+ .height = fival->height, -+ .which = V4L2_SUBDEV_FORMAT_ACTIVE, -+ }; -+ int ret; -+ -+ fmt = find_format_by_pix(dev, fival->pixel_format); -+ if (!fmt) -+ return -EINVAL; -+ -+ fie.code = fmt->code; -+ ret = v4l2_subdev_call(dev->sensor, pad, enum_frame_interval, -+ NULL, &fie); -+ if (ret) -+ return ret; -+ -+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; -+ fival->discrete = fie.interval; -+ -+ return 0; -+} -+ -+static int unicam_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_g_parm_cap(video_devdata(file), dev->sensor, a); -+} -+ -+static int unicam_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_s_parm_cap(video_devdata(file), dev->sensor, a); -+} -+ -+static int unicam_g_dv_timings(struct file *file, void *priv, -+ struct v4l2_dv_timings *timings) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, video, g_dv_timings, timings); -+} -+ -+static int unicam_s_dv_timings(struct file *file, void *priv, -+ struct v4l2_dv_timings *timings) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ struct v4l2_dv_timings current_timings; -+ int ret; -+ -+ ret = v4l2_subdev_call(dev->sensor, video, g_dv_timings, -+ ¤t_timings); -+ -+ if (ret < 0) -+ return ret; -+ -+ if (v4l2_match_dv_timings(timings, ¤t_timings, 0, false)) -+ return 0; -+ -+ if (vb2_is_busy(&node->buffer_queue)) -+ return -EBUSY; -+ -+ ret = v4l2_subdev_call(dev->sensor, video, s_dv_timings, timings); -+ -+ /* Force recomputation of bytesperline */ -+ node->v_fmt.fmt.pix.bytesperline = 0; -+ -+ unicam_reset_format(node); -+ -+ return ret; -+} -+ -+static int unicam_query_dv_timings(struct file *file, void *priv, -+ struct v4l2_dv_timings *timings) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, video, query_dv_timings, timings); -+} -+ -+static int unicam_enum_dv_timings(struct file *file, void *priv, -+ struct v4l2_enum_dv_timings *timings) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, pad, enum_dv_timings, timings); -+} -+ -+static int unicam_dv_timings_cap(struct file *file, void *priv, -+ struct v4l2_dv_timings_cap *cap) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ -+ return v4l2_subdev_call(dev->sensor, pad, dv_timings_cap, cap); -+} -+ -+static int unicam_subscribe_event(struct v4l2_fh *fh, -+ const struct v4l2_event_subscription *sub) -+{ -+ switch (sub->type) { -+ case V4L2_EVENT_FRAME_SYNC: -+ return v4l2_event_subscribe(fh, sub, 2, NULL); -+ case V4L2_EVENT_SOURCE_CHANGE: -+ return v4l2_event_subscribe(fh, sub, 4, NULL); -+ } -+ -+ return v4l2_ctrl_subscribe_event(fh, sub); -+} -+ -+static int unicam_log_status(struct file *file, void *fh) -+{ -+ struct unicam_node *node = video_drvdata(file); -+ struct unicam_device *dev = node->dev; -+ u32 reg; -+ -+ /* status for sub devices */ -+ v4l2_device_call_all(&dev->v4l2_dev, 0, core, log_status); -+ -+ unicam_info(dev, "-----Receiver status-----\n"); -+ unicam_info(dev, "V4L2 width/height: %ux%u\n", -+ node->v_fmt.fmt.pix.width, node->v_fmt.fmt.pix.height); -+ unicam_info(dev, "Mediabus format: %08x\n", node->fmt->code); -+ unicam_info(dev, "V4L2 format: %08x\n", -+ node->v_fmt.fmt.pix.pixelformat); -+ reg = reg_read(dev, UNICAM_IPIPE); -+ unicam_info(dev, "Unpacking/packing: %u / %u\n", -+ get_field(reg, UNICAM_PUM_MASK), -+ get_field(reg, UNICAM_PPM_MASK)); -+ unicam_info(dev, "----Live data----\n"); -+ unicam_info(dev, "Programmed stride: %4u\n", -+ reg_read(dev, UNICAM_IBLS)); -+ unicam_info(dev, "Detected resolution: %ux%u\n", -+ reg_read(dev, UNICAM_IHSTA), -+ reg_read(dev, UNICAM_IVSTA)); -+ unicam_info(dev, "Write pointer: %08x\n", -+ reg_read(dev, UNICAM_IBWP)); -+ -+ return 0; -+} -+ -+static void unicam_notify(struct v4l2_subdev *sd, -+ unsigned int notification, void *arg) -+{ -+ struct unicam_device *dev = to_unicam_device(sd->v4l2_dev); -+ -+ switch (notification) { -+ case V4L2_DEVICE_NOTIFY_EVENT: -+ v4l2_event_queue(&dev->node[IMAGE_PAD].video_dev, arg); -+ break; -+ default: -+ break; -+ } -+} + +static const struct vb2_ops unicam_video_qops = { + .wait_prepare = vb2_ops_wait_prepare, @@ -78261,60 +83776,6 @@ index 000000000000..59163f93b207 + .mmap = vb2_fop_mmap, +}; + -+/* unicam capture ioctl operations */ -+static const struct v4l2_ioctl_ops unicam_ioctl_ops = { -+ .vidioc_querycap = unicam_querycap, -+ .vidioc_enum_fmt_vid_cap = unicam_enum_fmt_vid_cap, -+ .vidioc_g_fmt_vid_cap = unicam_g_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = unicam_s_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = unicam_try_fmt_vid_cap, -+ -+ .vidioc_enum_fmt_meta_cap = unicam_enum_fmt_meta_cap, -+ .vidioc_g_fmt_meta_cap = unicam_g_fmt_meta_cap, -+ .vidioc_s_fmt_meta_cap = unicam_g_fmt_meta_cap, -+ .vidioc_try_fmt_meta_cap = unicam_g_fmt_meta_cap, -+ -+ .vidioc_enum_input = unicam_enum_input, -+ .vidioc_g_input = unicam_g_input, -+ .vidioc_s_input = unicam_s_input, -+ -+ .vidioc_querystd = unicam_querystd, -+ .vidioc_s_std = unicam_s_std, -+ .vidioc_g_std = unicam_g_std, -+ -+ .vidioc_g_edid = unicam_g_edid, -+ .vidioc_s_edid = unicam_s_edid, -+ -+ .vidioc_enum_framesizes = unicam_enum_framesizes, -+ .vidioc_enum_frameintervals = unicam_enum_frameintervals, -+ -+ .vidioc_g_selection = unicam_g_selection, -+ .vidioc_s_selection = unicam_s_selection, -+ -+ .vidioc_g_parm = unicam_g_parm, -+ .vidioc_s_parm = unicam_s_parm, -+ -+ .vidioc_s_dv_timings = unicam_s_dv_timings, -+ .vidioc_g_dv_timings = unicam_g_dv_timings, -+ .vidioc_query_dv_timings = unicam_query_dv_timings, -+ .vidioc_enum_dv_timings = unicam_enum_dv_timings, -+ .vidioc_dv_timings_cap = unicam_dv_timings_cap, -+ -+ .vidioc_reqbufs = vb2_ioctl_reqbufs, -+ .vidioc_create_bufs = vb2_ioctl_create_bufs, -+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, -+ .vidioc_querybuf = vb2_ioctl_querybuf, -+ .vidioc_qbuf = vb2_ioctl_qbuf, -+ .vidioc_dqbuf = vb2_ioctl_dqbuf, -+ .vidioc_expbuf = vb2_ioctl_expbuf, -+ .vidioc_streamon = vb2_ioctl_streamon, -+ .vidioc_streamoff = vb2_ioctl_streamoff, -+ -+ .vidioc_log_status = unicam_log_status, -+ .vidioc_subscribe_event = unicam_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -+}; -+ +static int +unicam_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, @@ -78365,11 +83826,11 @@ index 000000000000..59163f93b207 + unicam_put(node->dev); +} + -+static int register_node(struct unicam_device *unicam, struct unicam_node *node, -+ enum v4l2_buf_type type, int pad_id) ++static int unicam_set_default_format(struct unicam_device *unicam, ++ struct unicam_node *node, ++ int pad_id, ++ const struct unicam_fmt **ret_fmt) +{ -+ struct video_device *vdev; -+ struct vb2_queue *q; + struct v4l2_mbus_framefmt mbus_fmt = {0}; + const struct unicam_fmt *fmt; + int ret; @@ -78390,14 +83851,12 @@ index 000000000000..59163f93b207 + */ + fmt = get_first_supported_format(unicam); + -+ if (!fmt) -+ /* No compatible formats */ -+ return -EINVAL; -+ -+ mbus_fmt.code = fmt->code; -+ ret = __subdev_set_format(unicam, &mbus_fmt, pad_id); -+ if (ret) -+ return -EINVAL; ++ if (fmt) { ++ mbus_fmt.code = fmt->code; ++ ret = __subdev_set_format(unicam, &mbus_fmt, pad_id); ++ if (ret) ++ return -EINVAL; ++ } + } + if (mbus_fmt.field != V4L2_FIELD_NONE) { + /* Interlaced not supported - disable it now. */ @@ -78407,7 +83866,8 @@ index 000000000000..59163f93b207 + return -EINVAL; + } + -+ node->v_fmt.fmt.pix.pixelformat = fmt->fourcc ? fmt->fourcc ++ if (fmt) ++ node->v_fmt.fmt.pix.pixelformat = fmt->fourcc ? fmt->fourcc + : fmt->repacked_fourcc; + } else { + /* Fix this node format as embedded data. */ @@ -78415,14 +83875,69 @@ index 000000000000..59163f93b207 + node->v_fmt.fmt.meta.dataformat = fmt->fourcc; + } + ++ *ret_fmt = fmt; ++ ++ return 0; ++} ++ ++static void unicam_mc_set_default_format(struct unicam_node *node, int pad_id) ++{ ++ if (pad_id == IMAGE_PAD) { ++ struct v4l2_pix_format *pix_fmt = &node->v_fmt.fmt.pix; ++ ++ pix_fmt->width = 640; ++ pix_fmt->height = 480; ++ pix_fmt->field = V4L2_FIELD_NONE; ++ pix_fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601; ++ pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE; ++ pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB; ++ pix_fmt->pixelformat = formats[0].fourcc; ++ unicam_calc_format_size_bpl(node->dev, &formats[0], ++ &node->v_fmt); ++ node->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ node->fmt = &formats[0]; ++ } else { ++ const struct unicam_fmt *fmt; ++ ++ /* Fix this node format as embedded data. */ ++ fmt = find_format_by_code(MEDIA_BUS_FMT_SENSOR_DATA); ++ node->v_fmt.fmt.meta.dataformat = fmt->fourcc; ++ node->fmt = fmt; ++ ++ node->v_fmt.fmt.meta.buffersize = UNICAM_EMBEDDED_SIZE; ++ node->embedded_lines = 1; ++ node->v_fmt.type = V4L2_BUF_TYPE_META_CAPTURE; ++ } ++} ++ ++static int register_node(struct unicam_device *unicam, struct unicam_node *node, ++ enum v4l2_buf_type type, int pad_id) ++{ ++ struct video_device *vdev; ++ struct vb2_queue *q; ++ int ret; ++ + node->dev = unicam; + node->pad_id = pad_id; -+ node->fmt = fmt; + -+ /* Read current subdev format */ -+ unicam_reset_format(node); ++ if (!unicam->mc_api) { ++ const struct unicam_fmt *fmt; ++ ++ ret = unicam_set_default_format(unicam, node, pad_id, &fmt); ++ if (ret) ++ return ret; ++ node->fmt = fmt; ++ /* Read current subdev format */ ++ if (fmt) ++ unicam_reset_format(node); ++ } else { ++ unicam_mc_set_default_format(node, pad_id); ++ } + -+ if (v4l2_subdev_has_op(unicam->sensor, video, s_std)) { ++ if (!unicam->mc_api && ++ v4l2_subdev_has_op(unicam->sensor, video, s_std)) { + v4l2_std_id tvnorms; + + if (WARN_ON(!v4l2_subdev_has_op(unicam->sensor, video, @@ -78445,12 +83960,15 @@ index 000000000000..59163f93b207 + + vdev = &node->video_dev; + if (pad_id == IMAGE_PAD) { -+ /* Add controls from the subdevice */ -+ ret = v4l2_ctrl_add_handler(&unicam->ctrl_handler, -+ unicam->sensor->ctrl_handler, NULL, -+ true); -+ if (ret < 0) -+ return ret; ++ if (!unicam->mc_api) { ++ /* Add controls from the subdevice */ ++ ret = v4l2_ctrl_add_handler(&unicam->ctrl_handler, ++ unicam->sensor->ctrl_handler, ++ NULL, ++ true); ++ if (ret < 0) ++ return ret; ++ } + + /* + * If the sensor subdevice has any controls, associate the node @@ -78482,7 +84000,8 @@ index 000000000000..59163f93b207 + + vdev->release = unicam_node_release; + vdev->fops = &unicam_fops; -+ vdev->ioctl_ops = &unicam_ioctl_ops; ++ vdev->ioctl_ops = unicam->mc_api ? &unicam_mc_ioctl_ops : ++ &unicam_ioctl_ops; + vdev->v4l2_dev = &unicam->v4l2_dev; + vdev->vfl_dir = VFL_DIR_RX; + vdev->queue = q; @@ -78490,6 +84009,10 @@ index 000000000000..59163f93b207 + vdev->device_caps = (pad_id == IMAGE_PAD) ? + V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_META_CAPTURE; + vdev->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; ++ if (unicam->mc_api) { ++ vdev->device_caps |= V4L2_CAP_IO_MC; ++ vdev->entity.ops = &unicam_mc_entity_ops; ++ } + + /* Define the device names */ + snprintf(vdev->name, sizeof(vdev->name), "%s-%s", UNICAM_MODULE_NAME, @@ -78509,47 +84032,61 @@ index 000000000000..59163f93b207 + unicam_err(unicam, "Unable to allocate dummy buffer.\n"); + return -ENOMEM; + } -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, video, s_std)) { -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_STD); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUMSTD); -+ } -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, video, querystd)) -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERYSTD); -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, video, s_dv_timings)) { -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_EDID); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_EDID); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_DV_TIMINGS_CAP); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_DV_TIMINGS); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_DV_TIMINGS); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUM_DV_TIMINGS); -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERY_DV_TIMINGS); -+ } -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval)) -+ v4l2_disable_ioctl(&node->video_dev, -+ VIDIOC_ENUM_FRAMEINTERVALS); -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval)) -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_PARM); -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval)) -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_PARM); -+ -+ if (pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size)) -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUM_FRAMESIZES); -+ -+ if (node->pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, pad, set_selection)) -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_SELECTION); -+ -+ if (node->pad_id == METADATA_PAD || -+ !v4l2_subdev_has_op(unicam->sensor, pad, get_selection)) -+ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_SELECTION); ++ if (!unicam->mc_api) { ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, video, s_std)) { ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD); ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_STD); ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUMSTD); ++ } ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, video, querystd)) ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERYSTD); ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, video, s_dv_timings)) { ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_EDID); ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_EDID); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_DV_TIMINGS_CAP); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_G_DV_TIMINGS); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_S_DV_TIMINGS); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_DV_TIMINGS); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_QUERY_DV_TIMINGS); ++ } ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, pad, ++ enum_frame_interval)) ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_FRAMEINTERVALS); ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, video, ++ g_frame_interval)) ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_PARM); ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, video, ++ s_frame_interval)) ++ v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_PARM); ++ ++ if (pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, pad, ++ enum_frame_size)) ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_FRAMESIZES); ++ ++ if (node->pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, pad, set_selection)) ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_S_SELECTION); ++ ++ if (node->pad_id == METADATA_PAD || ++ !v4l2_subdev_has_op(unicam->sensor, pad, get_selection)) ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_G_SELECTION); ++ } + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { @@ -78567,7 +84104,8 @@ index 000000000000..59163f93b207 + node->registered = true; + + if (pad_id != METADATA_PAD || unicam->sensor_embedded_data) { -+ ret = media_create_pad_link(&unicam->sensor->entity, pad_id, ++ ret = media_create_pad_link(&unicam->sensor->entity, ++ node->src_pad_id, + &node->video_dev.entity, 0, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); @@ -78599,8 +84137,10 @@ index 000000000000..59163f93b207 + } +} + -+static int unicam_probe_complete(struct unicam_device *unicam) ++static int unicam_async_complete(struct v4l2_async_notifier *notifier) +{ ++ struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev); ++ unsigned int i, source_pads = 0; + int ret; + + unicam->v4l2_dev.notify = unicam_notify; @@ -78609,7 +84149,20 @@ index 000000000000..59163f93b207 + if (!unicam->sensor_config) + return -ENOMEM; + -+ unicam->sensor_embedded_data = (unicam->sensor->entity.num_pads >= 2); ++ for (i = 0; i < unicam->sensor->entity.num_pads; i++) { ++ if (unicam->sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) { ++ if (source_pads < MAX_NODES) { ++ unicam->node[source_pads].src_pad_id = i; ++ unicam_dbg(3, unicam, "source pad %u is index %u\n", ++ source_pads, i); ++ } ++ source_pads++; ++ } ++ } ++ if (!source_pads) { ++ unicam_err(unicam, "No source pads on sensor.\n"); ++ goto unregister; ++ } + + ret = register_node(unicam, &unicam->node[IMAGE_PAD], + V4L2_BUF_TYPE_VIDEO_CAPTURE, IMAGE_PAD); @@ -78618,14 +84171,21 @@ index 000000000000..59163f93b207 + goto unregister; + } + -+ ret = register_node(unicam, &unicam->node[METADATA_PAD], -+ V4L2_BUF_TYPE_META_CAPTURE, METADATA_PAD); -+ if (ret) { -+ unicam_err(unicam, "Unable to register metadata video device.\n"); -+ goto unregister; ++ if (source_pads >= 2) { ++ unicam->sensor_embedded_data = true; ++ ++ ret = register_node(unicam, &unicam->node[METADATA_PAD], ++ V4L2_BUF_TYPE_META_CAPTURE, METADATA_PAD); ++ if (ret) { ++ unicam_err(unicam, "Unable to register metadata video device.\n"); ++ goto unregister; ++ } + } + -+ ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev); ++ if (unicam->mc_api) ++ ret = v4l2_device_register_subdev_nodes(&unicam->v4l2_dev); ++ else ++ ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev); + if (ret) { + unicam_err(unicam, "Unable to register subdev nodes.\n"); + goto unregister; @@ -78645,13 +84205,6 @@ index 000000000000..59163f93b207 + return ret; +} + -+static int unicam_async_complete(struct v4l2_async_notifier *notifier) -+{ -+ struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev); -+ -+ return unicam_probe_complete(unicam); -+} -+ +static const struct v4l2_async_notifier_operations unicam_async_ops = { + .bound = unicam_async_bound, + .complete = unicam_async_complete, @@ -78760,7 +84313,7 @@ index 000000000000..59163f93b207 + dev->notifier.ops = &unicam_async_ops; + + dev->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; -+ dev->asd.match.fwnode = of_fwnode_handle(sensor_node); ++ dev->asd.match.fwnode = fwnode_graph_get_remote_endpoint(of_fwnode_handle(ep_node)); + ret = v4l2_async_notifier_add_subdev(&dev->notifier, &dev->asd); + if (ret) { + unicam_err(dev, "Error adding subdevice: %d\n", ret); @@ -78792,6 +84345,14 @@ index 000000000000..59163f93b207 + kref_init(&unicam->kref); + unicam->pdev = pdev; + ++ /* ++ * Adopt the current setting of the module parameter, and check if ++ * device tree requests it. ++ */ ++ unicam->mc_api = media_controller; ++ if (of_property_read_bool(pdev->dev.of_node, "brcm,media-controller")) ++ unicam->mc_api = true; ++ + unicam->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(unicam->base)) { + unicam_err(unicam, "Failed to get main io block\n"); @@ -79214,7 +84775,7 @@ index c278b9b0f102..05f2297cf583 100644 &rtl28xxu_props, "Leadtek WinFast DTV Dongle mini", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c -index 41f8410d08d6..517c4499f56d 100644 +index 41f8410d08d6..2099a4d814e4 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -275,6 +275,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id) @@ -79233,7 +84794,15 @@ index 41f8410d08d6..517c4499f56d 100644 case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; -@@ -1461,6 +1463,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, +@@ -1130,6 +1132,7 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_TEST_PATTERN_GREENR: return "Green (Red) Pixel Value"; + case V4L2_CID_TEST_PATTERN_BLUE: return "Blue Pixel Value"; + case V4L2_CID_TEST_PATTERN_GREENB: return "Green (Blue) Pixel Value"; ++ case V4L2_CID_NOTIFY_GAINS: return "Notify Gains"; + + /* Image processing controls */ + /* Keep the order of the 'case's the same as in v4l2-controls.h! */ +@@ -1461,6 +1464,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; break; @@ -79243,7 +84812,7 @@ index 41f8410d08d6..517c4499f56d 100644 case V4L2_CID_UNIT_CELL_SIZE: *type = V4L2_CTRL_TYPE_AREA; *flags |= V4L2_CTRL_FLAG_READ_ONLY; -@@ -1934,6 +1939,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, +@@ -1934,6 +1940,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, zero_padding(*p_hevc_slice_params); break; @@ -79253,7 +84822,7 @@ index 41f8410d08d6..517c4499f56d 100644 case V4L2_CTRL_TYPE_AREA: area = p; if (!area->width || !area->height) -@@ -2644,6 +2652,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, +@@ -2644,6 +2653,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); break; @@ -79264,10 +84833,10 @@ index 41f8410d08d6..517c4499f56d 100644 elem_size = sizeof(struct v4l2_area); break; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index 9eda8b91d17a..d72b462bb054 100644 +index 6d6d30dbbe68..2ee902f64ddc 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -1283,6 +1283,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) +@@ -1301,6 +1301,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_Y16_BE: descr = "16-bit Greyscale BE"; break; case V4L2_PIX_FMT_Y10BPACK: descr = "10-bit Greyscale (Packed)"; break; case V4L2_PIX_FMT_Y10P: descr = "10-bit Greyscale (MIPI Packed)"; break; @@ -79276,7 +84845,7 @@ index 9eda8b91d17a..d72b462bb054 100644 case V4L2_PIX_FMT_Y8I: descr = "Interleaved 8-bit Greyscale"; break; case V4L2_PIX_FMT_Y12I: descr = "Interleaved 12-bit Greyscale"; break; case V4L2_PIX_FMT_Z16: descr = "16-bit Depth"; break; -@@ -1325,6 +1327,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) +@@ -1343,6 +1345,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV61M: descr = "Y/CrCb 4:2:2 (N-C)"; break; case V4L2_PIX_FMT_NV12MT: descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break; case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; @@ -79285,7 +84854,7 @@ index 9eda8b91d17a..d72b462bb054 100644 case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_YUV422M: descr = "Planar YUV 4:2:2 (N-C)"; break; -@@ -1402,6 +1406,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) +@@ -1420,6 +1424,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_META_FMT_UVC: descr = "UVC Payload Header Metadata"; break; case V4L2_META_FMT_D4XX: descr = "Intel D4xx UVC Metadata"; break; case V4L2_META_FMT_VIVID: descr = "Vivid Metadata"; break; @@ -79295,7 +84864,7 @@ index 9eda8b91d17a..d72b462bb054 100644 default: /* Compressed formats */ diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c -index b221b4e438a1..fb8708ddc1dc 100644 +index ad14d5214106..9ddbb7a1e96b 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -301,9 +301,10 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, @@ -79321,8 +84890,75 @@ index b221b4e438a1..fb8708ddc1dc 100644 spin_lock_irqsave(&m2m_dev->job_spinlock, flags); schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); +diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c +index fbf0dcb313c8..bf3aa9252458 100644 +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -768,21 +768,55 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, + struct v4l2_subdev_format *source_fmt, + struct v4l2_subdev_format *sink_fmt) + { ++ bool pass = true; ++ + /* The width, height and code must match. */ +- if (source_fmt->format.width != sink_fmt->format.width +- || source_fmt->format.height != sink_fmt->format.height +- || source_fmt->format.code != sink_fmt->format.code) +- return -EPIPE; ++ if (source_fmt->format.width != sink_fmt->format.width) { ++ dev_dbg(sd->entity.graph_obj.mdev->dev, ++ "%s: width does not match (source %u, sink %u)\n", ++ __func__, ++ source_fmt->format.width, sink_fmt->format.width); ++ pass = false; ++ } ++ ++ if (source_fmt->format.height != sink_fmt->format.height) { ++ dev_dbg(sd->entity.graph_obj.mdev->dev, ++ "%s: height does not match (source %u, sink %u)\n", ++ __func__, ++ source_fmt->format.height, sink_fmt->format.height); ++ pass = false; ++ } ++ ++ if (source_fmt->format.code != sink_fmt->format.code) { ++ dev_dbg(sd->entity.graph_obj.mdev->dev, ++ "%s: media bus code does not match (source 0x%8.8x, sink 0x%8.8x)\n", ++ __func__, ++ source_fmt->format.code, sink_fmt->format.code); ++ pass = false; ++ } + + /* The field order must match, or the sink field order must be NONE + * to support interlaced hardware connected to bridges that support + * progressive formats only. + */ + if (source_fmt->format.field != sink_fmt->format.field && +- sink_fmt->format.field != V4L2_FIELD_NONE) +- return -EPIPE; ++ sink_fmt->format.field != V4L2_FIELD_NONE) { ++ dev_dbg(sd->entity.graph_obj.mdev->dev, ++ "%s: field does not match (source %u, sink %u)\n", ++ __func__, ++ source_fmt->format.field, sink_fmt->format.field); ++ pass = false; ++ } + +- return 0; ++ if (pass) ++ return 0; ++ ++ dev_dbg(sd->entity.graph_obj.mdev->dev, ++ "%s: link was \"%s\":%u -> \"%s\":%u\n", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ return -EPIPE; + } + EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default); + diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index b8847ae04d93..525cb2c70538 100644 +index 3f9f84f9f288..b515de80b6c1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -11,6 +11,14 @@ config MFD_CORE @@ -79341,17 +84977,17 @@ index b8847ae04d93..525cb2c70538 100644 tristate "AMD CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 1780019d2474..d6091f3b1ca3 100644 +index ce8f1c0583d5..dfbfa7b7f064 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -263,6 +263,7 @@ obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o +@@ -264,6 +264,7 @@ obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o obj-$(CONFIG_MFD_STMFX) += stmfx.o obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o +obj-$(CONFIG_MFD_RPISENSE_CORE) += rpisense-core.o - obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o - obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o + obj-$(CONFIG_LPC_CHIP3) += lpc_sunway_chip3.o + obj-$(CONFIG_SUNWAY_SUPERIO_AST2400) += sunway_ast2400.o diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c index 42fe67f1538e..f66f92fe28c3 100644 --- a/drivers/mfd/bcm2835-pm.c @@ -79546,7 +85182,7 @@ index 000000000000..6cfd63e5e8b8 +MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index fafa8b0d8099..5b01870e8f6f 100644 +index 140716083ab8..43147f3c1fcc 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -9,6 +9,14 @@ config SENSORS_LIS3LV02D @@ -79565,7 +85201,7 @@ index fafa8b0d8099..5b01870e8f6f 100644 tristate "Analog Devices Digital Potentiometers" depends on (I2C || SPI) && SYSFS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index d23231e73330..3fd91279bdd9 100644 +index 3615763234a6..b8803cada725 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o @@ -80538,7 +86174,7 @@ index 000000000000..f1a7f6a3e966 +MODULE_DESCRIPTION("Device driver for BCM2835's secondary memory interface"); +MODULE_AUTHOR("Luke Wren "); diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c -index 94caee49da99..da599f075bc2 100644 +index 6622e3262187..e27fd8e711cc 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -165,6 +165,13 @@ static DEFINE_MUTEX(open_lock); @@ -80555,7 +86191,7 @@ index 94caee49da99..da599f075bc2 100644 static inline int mmc_blk_part_switch(struct mmc_card *card, unsigned int part_type); static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, -@@ -2897,6 +2904,7 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2901,6 +2908,7 @@ static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; char cap_str[10]; @@ -80563,7 +86199,7 @@ index 94caee49da99..da599f075bc2 100644 /* * Check that the card supports the command class(es) we need. -@@ -2904,7 +2912,16 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2908,7 +2916,16 @@ static int mmc_blk_probe(struct mmc_card *card) if (!(card->csd.cmdclass & CCC_BLOCK_READ)) return -ENODEV; @@ -80581,7 +86217,7 @@ index 94caee49da99..da599f075bc2 100644 card->complete_wq = alloc_workqueue("mmc_complete", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); -@@ -2919,9 +2936,14 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2923,9 +2940,14 @@ static int mmc_blk_probe(struct mmc_card *card) string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); @@ -80599,7 +86235,7 @@ index 94caee49da99..da599f075bc2 100644 if (mmc_blk_alloc_parts(card, md)) goto out; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index b5f3f160c842..c73368d5d6b2 100644 +index eb82f6aac951..6870e8bbd2ec 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1874,7 +1874,8 @@ EXPORT_SYMBOL(mmc_erase); @@ -80613,12 +86249,12 @@ index b5f3f160c842..c73368d5d6b2 100644 return 0; } diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h -index d68e6e513a4f..e41bc00ece42 100644 +index c8c0f50a2076..20380a8fdba2 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h -@@ -99,6 +99,14 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { - MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_TRIM_BROKEN), +@@ -105,6 +105,14 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { + MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_DISCARD), + /* + * On some Kingston SD cards, multiple erases of less than 64 @@ -80632,7 +86268,7 @@ index d68e6e513a4f..e41bc00ece42 100644 }; diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 31481c9fcc2e..49f56beb5fde 100644 +index 82e1fbd6b2ff..66b2a205910c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -5,6 +5,45 @@ @@ -84503,7 +90139,7 @@ index b9eb2ec61a83..404870e6b759 100644 .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index b1e1d327cb8e..30d5f2debfd9 100644 +index d42e86cdff12..0533339d7979 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -41,7 +41,7 @@ @@ -84515,7 +90151,7 @@ index b1e1d327cb8e..30d5f2debfd9 100644 #define MAX_TUNING_LOOP 40 -@@ -3127,7 +3127,7 @@ static void sdhci_timeout_timer(struct timer_list *t) +@@ -3145,7 +3145,7 @@ static void sdhci_timeout_timer(struct timer_list *t) spin_lock_irqsave(&host->lock, flags); if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { @@ -84524,7 +90160,7 @@ index b1e1d327cb8e..30d5f2debfd9 100644 mmc_hostname(host->mmc)); sdhci_dumpregs(host); -@@ -3149,7 +3149,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) +@@ -3167,7 +3167,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) if (host->data || host->data_cmd || (host->cmd && sdhci_data_line_cmd(host->cmd))) { @@ -84534,7 +90170,7 @@ index b1e1d327cb8e..30d5f2debfd9 100644 sdhci_dumpregs(host); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -index aac837aa2c24..18460c3536dc 100644 +index 6ee6c34f28f2..a48f3c482b01 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -67,6 +67,9 @@ @@ -84547,7 +90183,7 @@ index aac837aa2c24..18460c3536dc 100644 static inline void bcmgenet_writel(u32 value, void __iomem *offset) { -@@ -2430,6 +2433,11 @@ static void reset_umac(struct bcmgenet_priv *priv) +@@ -2439,6 +2442,11 @@ static void reset_umac(struct bcmgenet_priv *priv) bcmgenet_rbuf_ctrl_set(priv, 0); udelay(10); @@ -84559,7 +90195,7 @@ index aac837aa2c24..18460c3536dc 100644 /* issue soft reset and disable MAC while updating its registers */ bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD); udelay(2); -@@ -2599,7 +2607,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, +@@ -2608,7 +2616,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX); bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX); @@ -84568,7 +90204,7 @@ index aac837aa2c24..18460c3536dc 100644 /* Disable rate control for now */ bcmgenet_tdma_ring_writel(priv, index, flow_period_val, TDMA_FLOW_PERIOD); -@@ -3240,7 +3248,7 @@ static void bcmgenet_get_hw_addr(struct bcmgenet_priv *priv, +@@ -3249,7 +3257,7 @@ static void bcmgenet_get_hw_addr(struct bcmgenet_priv *priv, } /* Returns a reusable dma control register value */ @@ -84577,7 +90213,7 @@ index aac837aa2c24..18460c3536dc 100644 { unsigned int i; u32 reg; -@@ -3265,6 +3273,14 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) +@@ -3274,6 +3282,14 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) udelay(10); bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); @@ -84592,7 +90228,7 @@ index aac837aa2c24..18460c3536dc 100644 return dma_ctrl; } -@@ -3328,8 +3344,8 @@ static int bcmgenet_open(struct net_device *dev) +@@ -3337,8 +3353,8 @@ static int bcmgenet_open(struct net_device *dev) bcmgenet_set_hw_addr(priv, dev->dev_addr); @@ -84603,7 +90239,7 @@ index aac837aa2c24..18460c3536dc 100644 /* Reinitialize TDMA and RDMA and SW housekeeping */ ret = bcmgenet_init_dma(priv); -@@ -4062,9 +4078,12 @@ static int bcmgenet_probe(struct platform_device *pdev) +@@ -4077,9 +4093,12 @@ static int bcmgenet_probe(struct platform_device *pdev) netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1); /* Set default coalescing parameters */ @@ -84617,7 +90253,7 @@ index aac837aa2c24..18460c3536dc 100644 /* libphy will determine the link state */ netif_carrier_off(dev); -@@ -4180,7 +4199,7 @@ static int bcmgenet_resume(struct device *d) +@@ -4195,7 +4214,7 @@ static int bcmgenet_resume(struct device *d) bcmgenet_hfb_create_rxnfc_filter(priv, rule); /* Disable RX/TX DMA and flush TX queues */ @@ -84653,10 +90289,10 @@ index f9e91304d232..7abd5ddebd8e 100644 /* Initialize link state variables that bcmgenet_mii_setup() uses */ priv->old_link = -1; diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c -index dbed15dc0fe7..8b0ac38742d0 100644 +index 0cde17bd743f..2122c7171320 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c -@@ -82,6 +82,11 @@ static int bcm54210e_config_init(struct phy_device *phydev) +@@ -83,6 +83,11 @@ static int bcm54210e_config_init(struct phy_device *phydev) return 0; } @@ -84668,7 +90304,7 @@ index dbed15dc0fe7..8b0ac38742d0 100644 static int bcm54612e_config_init(struct phy_device *phydev) { int reg; -@@ -252,7 +257,8 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) +@@ -253,7 +258,8 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 && BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M && BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54810 && @@ -84678,7 +90314,7 @@ index dbed15dc0fe7..8b0ac38742d0 100644 return; val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); -@@ -313,6 +319,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) +@@ -314,6 +320,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) static int bcm54xx_config_init(struct phy_device *phydev) { int reg, err, val; @@ -84688,7 +90324,7 @@ index dbed15dc0fe7..8b0ac38742d0 100644 reg = phy_read(phydev, MII_BCM54XX_ECR); if (reg < 0) -@@ -350,6 +359,9 @@ static int bcm54xx_config_init(struct phy_device *phydev) +@@ -351,6 +360,9 @@ static int bcm54xx_config_init(struct phy_device *phydev) case PHY_ID_BCM54612E: err = bcm54612e_config_init(phydev); break; @@ -84698,7 +90334,7 @@ index dbed15dc0fe7..8b0ac38742d0 100644 case PHY_ID_BCM54616S: err = bcm54616s_config_init(phydev); break; -@@ -368,17 +380,15 @@ static int bcm54xx_config_init(struct phy_device *phydev) +@@ -369,17 +381,15 @@ static int bcm54xx_config_init(struct phy_device *phydev) bcm54xx_phydsp_config(phydev); @@ -84720,7 +90356,7 @@ index dbed15dc0fe7..8b0ac38742d0 100644 bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); return 0; -@@ -762,12 +772,20 @@ static struct phy_driver broadcom_drivers[] = { +@@ -783,12 +793,20 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, }, { .phy_id = PHY_ID_BCM54210E, @@ -84742,7 +90378,7 @@ index dbed15dc0fe7..8b0ac38742d0 100644 }, { .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, -@@ -923,7 +941,8 @@ module_phy_driver(broadcom_drivers); +@@ -945,7 +963,8 @@ module_phy_driver(broadcom_drivers); static struct mdio_device_id __maybe_unused broadcom_tbl[] = { { PHY_ID_BCM5411, 0xfffffff0 }, { PHY_ID_BCM5421, 0xfffffff0 }, @@ -84798,10 +90434,19 @@ index a644e8e5071c..15e0a7383f68 100644 priv->chip_id = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_ID); priv->chip_rev = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_REV); diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c -index caf7291ffaf8..9983eeded624 100644 +index caf7291ffaf8..65ccc94a9282 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c -@@ -195,12 +195,12 @@ static int lan87xx_read_status(struct phy_device *phydev) +@@ -185,6 +185,8 @@ static int lan87xx_read_status(struct phy_device *phydev) + int err = genphy_read_status(phydev); + + if (!phydev->link && priv->energy_enable) { ++ int energy_detected; ++ + /* Disable EDPD to wake up PHY */ + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); + if (rc < 0) +@@ -195,12 +197,12 @@ static int lan87xx_read_status(struct phy_device *phydev) if (rc < 0) return rc; @@ -84812,10 +90457,27 @@ index caf7291ffaf8..9983eeded624 100644 read_poll_timeout(phy_read, rc, rc & MII_LAN83C185_ENERGYON || rc < 0, - 10000, 640000, true, phydev, -+ 10000, 1500000, true, phydev, ++ 150000, 1500000, true, phydev, MII_LAN83C185_CTRL_STATUS); if (rc < 0) return rc; +@@ -210,10 +212,16 @@ static int lan87xx_read_status(struct phy_device *phydev) + if (rc < 0) + return rc; + ++ energy_detected = !!(rc & MII_LAN83C185_ENERGYON); ++ + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, + rc | MII_LAN83C185_EDPWRDOWN); + if (rc < 0) + return rc; ++ ++ /* Save CPU and power by deferring the next poll */ ++ if (!energy_detected) ++ msleep(2000); + } + + return err; diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 99fd12be2111..99381e6bea78 100644 --- a/drivers/net/usb/Makefile @@ -84830,10 +90492,10 @@ index 99fd12be2111..99381e6bea78 100644 obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_SR9700) += sr9700.o diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c -index a5cd42bae962..2c54e4eadde6 100644 +index 6f7b70522d92..54b3eb586b7e 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c -@@ -425,6 +425,20 @@ static int msg_level = -1; +@@ -427,6 +427,20 @@ static int msg_level = -1; module_param(msg_level, int, 0); MODULE_PARM_DESC(msg_level, "Override default message level"); @@ -84854,7 +90516,7 @@ index a5cd42bae962..2c54e4eadde6 100644 static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) { u32 *buf = kmalloc(sizeof(u32), GFP_KERNEL); -@@ -1167,6 +1181,9 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) +@@ -1169,6 +1183,9 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) if (unlikely(ret < 0)) return -EIO; @@ -84864,7 +90526,15 @@ index a5cd42bae962..2c54e4eadde6 100644 mutex_lock(&phydev->lock); phy_read_status(phydev); link = phydev->link; -@@ -2166,6 +2183,22 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) +@@ -1668,6 +1685,7 @@ static const struct ethtool_ops lan78xx_ethtool_ops = { + .set_link_ksettings = lan78xx_set_link_ksettings, + .get_regs_len = lan78xx_get_regs_len, + .get_regs = lan78xx_get_regs, ++ .get_ts_info = ethtool_op_get_ts_info, + }; + + static void lan78xx_init_mac_address(struct lan78xx_net *dev) +@@ -2168,6 +2186,22 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) mii_adv_to_linkmode_adv_t(fc, mii_adv); linkmode_or(phydev->advertising, fc, phydev->advertising); @@ -84887,7 +90557,7 @@ index a5cd42bae962..2c54e4eadde6 100644 if (phydev->mdio.dev.of_node) { u32 reg; int len; -@@ -2461,6 +2494,11 @@ static int lan78xx_reset(struct lan78xx_net *dev) +@@ -2463,6 +2497,11 @@ static int lan78xx_reset(struct lan78xx_net *dev) int ret = 0; unsigned long timeout; u8 sig; @@ -84899,7 +90569,7 @@ index a5cd42bae962..2c54e4eadde6 100644 ret = lan78xx_read_reg(dev, HW_CFG, &buf); buf |= HW_CFG_LRST_; -@@ -2514,6 +2552,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) +@@ -2516,6 +2555,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) ret = lan78xx_read_reg(dev, HW_CFG, &buf); buf |= HW_CFG_MEF_; @@ -84909,7 +90579,7 @@ index a5cd42bae962..2c54e4eadde6 100644 ret = lan78xx_write_reg(dev, HW_CFG, buf); ret = lan78xx_read_reg(dev, USB_CFG0, &buf); -@@ -2569,6 +2610,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) +@@ -2571,6 +2613,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; } } @@ -84919,7 +90589,7 @@ index a5cd42bae962..2c54e4eadde6 100644 ret = lan78xx_write_reg(dev, MAC_CR, buf); ret = lan78xx_read_reg(dev, MAC_TX, &buf); -@@ -2898,8 +2942,14 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) +@@ -2900,8 +2945,14 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; @@ -84936,7 +90606,7 @@ index a5cd42bae962..2c54e4eadde6 100644 if (DEFAULT_VLAN_RX_OFFLOAD) dev->net->features |= NETIF_F_HW_VLAN_CTAG_RX; -@@ -3122,7 +3172,7 @@ static int rx_submit(struct lan78xx_net *dev, struct urb *urb, gfp_t flags) +@@ -3124,7 +3175,7 @@ static int rx_submit(struct lan78xx_net *dev, struct urb *urb, gfp_t flags) size_t size = dev->rx_urb_size; int ret = 0; @@ -84945,7 +90615,7 @@ index a5cd42bae962..2c54e4eadde6 100644 if (!skb) { usb_free_urb(urb); return -ENOMEM; -@@ -3726,7 +3776,13 @@ static int lan78xx_probe(struct usb_interface *intf, +@@ -3728,7 +3779,13 @@ static int lan78xx_probe(struct usb_interface *intf, netdev->max_mtu = MAX_SINGLE_PACKET_SIZE; netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER); @@ -84961,7 +90631,7 @@ index a5cd42bae962..2c54e4eadde6 100644 buf = kmalloc(maxp, GFP_KERNEL); if (buf) { diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c -index 63b64fa7f33c..bf402dfd0c2c 100644 +index 84f44d00d4d9..b481ee3382fe 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -26,9 +26,10 @@ @@ -85546,7 +91216,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static int rtl8152_set_mac_address(struct net_device *netdev, void *p) { struct r8152 *tp = netdev_priv(netdev); -@@ -2410,11 +2572,9 @@ static void tx_bottom(struct r8152 *tp) +@@ -2412,11 +2574,9 @@ static void tx_bottom(struct r8152 *tp) } while (res == 0); } @@ -85560,7 +91230,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; -@@ -2612,7 +2772,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, +@@ -2614,7 +2774,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, static void r8152b_reset_packet_filter(struct r8152 *tp) { @@ -85569,7 +91239,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC); ocp_data &= ~FMC_FCR_MCU_EN; -@@ -2623,45 +2783,78 @@ static void r8152b_reset_packet_filter(struct r8152 *tp) +@@ -2625,45 +2785,78 @@ static void r8152b_reset_packet_filter(struct r8152 *tp) static void rtl8152_nic_reset(struct r8152 *tp) { @@ -85670,7 +91340,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } static void rxdy_gated_en(struct r8152 *tp, bool enable) -@@ -2759,6 +2952,29 @@ static int rtl_stop_rx(struct r8152 *tp) +@@ -2761,6 +2954,29 @@ static int rtl_stop_rx(struct r8152 *tp) return 0; } @@ -85700,7 +91370,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp) { ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN, -@@ -2778,6 +2994,7 @@ static int rtl_enable(struct r8152 *tp) +@@ -2780,6 +2996,7 @@ static int rtl_enable(struct r8152 *tp) switch (tp->version) { case RTL_VER_08: case RTL_VER_09: @@ -85708,7 +91378,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 r8153b_rx_agg_chg_indicate(tp); break; default: -@@ -2815,6 +3032,7 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp) +@@ -2817,6 +3034,7 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp) case RTL_VER_08: case RTL_VER_09: @@ -85716,7 +91386,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 /* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 128ns. */ -@@ -2824,6 +3042,18 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp) +@@ -2826,6 +3044,18 @@ static void r8153_set_rx_early_timeout(struct r8152 *tp) ocp_data); break; @@ -85735,7 +91405,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 default: break; } -@@ -2843,8 +3073,19 @@ static void r8153_set_rx_early_size(struct r8152 *tp) +@@ -2845,8 +3075,19 @@ static void r8153_set_rx_early_size(struct r8152 *tp) break; case RTL_VER_08: case RTL_VER_09: @@ -85755,7 +91425,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 break; default: WARN_ON_ONCE(1); -@@ -2854,6 +3095,8 @@ static void r8153_set_rx_early_size(struct r8152 *tp) +@@ -2856,6 +3097,8 @@ static void r8153_set_rx_early_size(struct r8152 *tp) static int rtl8153_enable(struct r8152 *tp) { @@ -85764,7 +91434,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (test_bit(RTL8152_UNPLUG, &tp->flags)) return -ENODEV; -@@ -2862,15 +3105,20 @@ static int rtl8153_enable(struct r8152 *tp) +@@ -2864,15 +3107,20 @@ static int rtl8153_enable(struct r8152 *tp) r8153_set_rx_early_timeout(tp); r8153_set_rx_early_size(tp); @@ -85787,7 +91457,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } return rtl_enable(tp); -@@ -2935,12 +3183,40 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable) +@@ -2937,12 +3185,40 @@ static void rtl_rx_vlan_en(struct r8152 *tp, bool enable) { u32 ocp_data; @@ -85834,7 +91504,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } static int rtl8152_set_features(struct net_device *dev, -@@ -3033,6 +3309,40 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts) +@@ -3035,6 +3311,40 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts) device_set_wakeup_enable(&tp->udev->dev, false); } @@ -85875,7 +91545,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static void r8153_u1u2en(struct r8152 *tp, bool enable) { u8 u1u2[8]; -@@ -3092,6 +3402,9 @@ static void r8153b_ups_flags(struct r8152 *tp) +@@ -3094,6 +3404,9 @@ static void r8153b_ups_flags(struct r8152 *tp) if (tp->ups_info.eee_cmod_lv) ups_flags |= UPS_FLAGS_EEE_CMOD_LV_EN; @@ -85885,7 +91555,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (tp->ups_info._10m_ckdiv) ups_flags |= UPS_FLAGS_EN_10M_CKDIV; -@@ -3142,10 +3455,104 @@ static void r8153b_ups_flags(struct r8152 *tp) +@@ -3144,10 +3457,104 @@ static void r8153b_ups_flags(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); } @@ -85991,7 +91661,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (enable) { sram_write(tp, 0x8045, 0); /* 10M abiq&ldvbias */ sram_write(tp, 0x804d, 0x1222); /* 100M short abiq&ldvbias */ -@@ -3156,11 +3563,7 @@ static void r8153b_green_en(struct r8152 *tp, bool enable) +@@ -3158,11 +3565,7 @@ static void r8153b_green_en(struct r8152 *tp, bool enable) sram_write(tp, 0x805d, 0x2444); /* 1000M short abiq&ldvbias */ } @@ -86004,7 +91674,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } static u16 r8153_phy_status(struct r8152 *tp, u16 desired) -@@ -3197,61 +3600,137 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable) +@@ -3199,61 +3602,137 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable) ocp_data |= UPS_EN | USP_PREWAKE | PHASE2_EN; ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); @@ -86182,7 +91852,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); } -@@ -3363,7 +3842,39 @@ static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable) +@@ -3365,7 +3844,39 @@ static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable) r8153b_ups_en(tp, false); r8153_queue_wake(tp, false); rtl_runtime_suspend_enable(tp, false); @@ -86223,7 +91893,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 r8153b_u1u2en(tp, true); } } -@@ -3388,14 +3899,19 @@ static void r8153_teredo_off(struct r8152 *tp) +@@ -3390,14 +3901,19 @@ static void r8153_teredo_off(struct r8152 *tp) case RTL_VER_08: case RTL_VER_09: @@ -86246,7 +91916,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE); -@@ -3430,6 +3946,12 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) +@@ -3432,6 +3948,12 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) break; case RTL_VER_08: case RTL_VER_09: @@ -86259,7 +91929,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 default: if (type == MCU_TYPE_USB) { ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0); -@@ -3462,65 +3984,238 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) +@@ -3464,65 +3986,238 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) ocp_write_word(tp, type, PLA_BP_BA, 0); } @@ -86523,7 +92193,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static bool rtl8152_is_fw_phy_nc_ok(struct r8152 *tp, struct fw_phy_nc *phy) { u32 length; -@@ -3622,6 +4317,11 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac) +@@ -3624,6 +4319,11 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac) case RTL_VER_06: case RTL_VER_08: case RTL_VER_09: @@ -86535,7 +92205,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 fw_reg = 0xf800; bp_ba_addr = PLA_BP_BA; bp_en_addr = PLA_BP_EN; -@@ -3645,6 +4345,11 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac) +@@ -3647,6 +4347,11 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac) break; case RTL_VER_08: case RTL_VER_09: @@ -86547,7 +92217,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 fw_reg = 0xe600; bp_ba_addr = USB_BP_BA; bp_en_addr = USB_BP2_EN; -@@ -3772,10 +4477,7 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw) +@@ -3774,10 +4479,7 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw) { const struct firmware *fw = rtl_fw->fw; struct fw_header *fw_hdr = (struct fw_header *)fw->data; @@ -86559,7 +92229,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 long ret = -EFAULT; int i; -@@ -3804,50 +4506,56 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw) +@@ -3806,50 +4508,56 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw) goto fail; goto fw_end; case RTL_FW_PLA: @@ -86627,7 +92297,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 dev_err(&tp->intf->dev, "Check PHY_STOP fail\n"); goto fail; -@@ -3858,53 +4566,336 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw) +@@ -3860,53 +4568,336 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw) "Invalid length for PHY_STOP\n"); goto fail; } @@ -86990,7 +92660,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 u16 mode_reg, bp_index; u32 length, i, num; __le16 *data; -@@ -3956,6 +4947,12 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) +@@ -3958,6 +4949,12 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) return; } @@ -87003,7 +92673,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 rtl_clear_bp(tp, type); /* Enable backup/restore of MACDBG. This is required after clearing PLA -@@ -3991,7 +4988,6 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) +@@ -3993,7 +4990,6 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) ocp_write_word(tp, type, bp_en_addr, __le16_to_cpu(mac->bp_en_value)); @@ -87011,7 +92681,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (fw_ver_reg) ocp_write_byte(tp, MCU_TYPE_USB, fw_ver_reg, mac->fw_ver_data); -@@ -3999,14 +4995,14 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) +@@ -4001,14 +4997,14 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) dev_dbg(&tp->intf->dev, "successfully applied %s\n", mac->info); } @@ -87028,7 +92698,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (IS_ERR_OR_NULL(rtl_fw->fw)) return; -@@ -4028,18 +5024,40 @@ static void rtl8152_apply_firmware(struct r8152 *tp) +@@ -4030,18 +5026,40 @@ static void rtl8152_apply_firmware(struct r8152 *tp) rtl8152_fw_mac_apply(tp, (struct fw_mac *)block); break; case RTL_FW_PHY_START: @@ -87072,7 +92742,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 default: break; } -@@ -4186,6 +5204,22 @@ static void r8153_eee_en(struct r8152 *tp, bool enable) +@@ -4188,6 +5206,22 @@ static void r8153_eee_en(struct r8152 *tp, bool enable) tp->ups_info.eee = enable; } @@ -87095,7 +92765,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static void rtl_eee_enable(struct r8152 *tp, bool enable) { switch (tp->version) { -@@ -4207,6 +5241,7 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable) +@@ -4209,6 +5243,7 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable) case RTL_VER_06: case RTL_VER_08: case RTL_VER_09: @@ -87103,7 +92773,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (enable) { r8153_eee_en(tp, true); ocp_reg_write(tp, OCP_EEE_ADV, tp->eee_adv); -@@ -4215,6 +5250,19 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable) +@@ -4217,6 +5252,19 @@ static void rtl_eee_enable(struct r8152 *tp, bool enable) ocp_reg_write(tp, OCP_EEE_ADV, 0); } break; @@ -87123,7 +92793,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 default: break; } -@@ -4240,7 +5288,7 @@ static void rtl8152_disable(struct r8152 *tp) +@@ -4242,7 +5290,7 @@ static void rtl8152_disable(struct r8152 *tp) static void r8152b_hw_phy_cfg(struct r8152 *tp) { @@ -87132,7 +92802,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 rtl_eee_enable(tp, tp->eee_en); r8152_aldps_en(tp, true); r8152b_enable_fc(tp); -@@ -4261,6 +5309,20 @@ static void wait_oob_link_list_ready(struct r8152 *tp) +@@ -4263,6 +5311,20 @@ static void wait_oob_link_list_ready(struct r8152 *tp) } } @@ -87153,7 +92823,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static void r8152b_exit_oob(struct r8152 *tp) { u32 ocp_data; -@@ -4311,7 +5373,7 @@ static void r8152b_exit_oob(struct r8152 *tp) +@@ -4313,7 +5375,7 @@ static void r8152b_exit_oob(struct r8152 *tp) } /* TX share fifo free credit full threshold */ @@ -87162,7 +92832,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD); ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH); -@@ -4488,6 +5550,36 @@ static int r8153b_post_firmware_1(struct r8152 *tp) +@@ -4490,6 +5552,36 @@ static int r8153b_post_firmware_1(struct r8152 *tp) return 0; } @@ -87199,7 +92869,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static void r8153_aldps_en(struct r8152 *tp, bool enable) { u16 data; -@@ -4522,7 +5614,7 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) +@@ -4524,7 +5616,7 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) /* disable EEE before updating the PHY parameters */ rtl_eee_enable(tp, false); @@ -87208,7 +92878,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (tp->version == RTL_VER_03) { data = ocp_reg_read(tp, OCP_EEE_CFG); -@@ -4590,13 +5682,37 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) +@@ -4592,13 +5684,37 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) u32 ocp_data; u16 data; @@ -87247,7 +92917,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); -@@ -4637,7 +5753,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) +@@ -4639,7 +5755,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); /* Advnace EEE */ @@ -87256,7 +92926,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 data = ocp_reg_read(tp, OCP_POWER_CFG); data |= EEE_CLKDIV_EN; ocp_reg_write(tp, OCP_POWER_CFG, data); -@@ -4654,7 +5770,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) +@@ -4656,7 +5772,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5)); tp->ups_info._250m_ckdiv = true; @@ -87265,7 +92935,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } if (tp->eee_en) -@@ -4666,6 +5782,19 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) +@@ -4668,6 +5784,19 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) set_bit(PHY_RESET, &tp->flags); } @@ -87285,7 +92955,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static void r8153_first_init(struct r8152 *tp) { u32 ocp_data; -@@ -4698,9 +5827,7 @@ static void r8153_first_init(struct r8152 *tp) +@@ -4700,9 +5829,7 @@ static void r8153_first_init(struct r8152 *tp) rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX); @@ -87296,7 +92966,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); ocp_data |= TCR0_AUTO_FIFO; -@@ -4735,8 +5862,7 @@ static void r8153_enter_oob(struct r8152 *tp) +@@ -4737,8 +5864,7 @@ static void r8153_enter_oob(struct r8152 *tp) wait_oob_link_list_ready(tp); @@ -87306,7 +92976,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 switch (tp->version) { case RTL_VER_03: -@@ -4750,6 +5876,7 @@ static void r8153_enter_oob(struct r8152 *tp) +@@ -4752,6 +5878,7 @@ static void r8153_enter_oob(struct r8152 *tp) case RTL_VER_08: case RTL_VER_09: @@ -87314,7 +92984,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 /* Clear teredo wake event. bit[15:8] is the teredo wakeup * type. Set it to zero. bits[7:0] are the W1C bits about * the events. Set them to all 1 to clear them. -@@ -4786,27 +5913,117 @@ static void rtl8153_disable(struct r8152 *tp) +@@ -4788,27 +5915,117 @@ static void rtl8153_disable(struct r8152 *tp) r8153_aldps_en(tp, true); } @@ -87450,7 +93120,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 bmcr = BMCR_SPEED100; if (duplex == DUPLEX_FULL) { bmcr |= BMCR_FULLDPLX; -@@ -4834,58 +6051,73 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, +@@ -4836,58 +6053,73 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, tp->mii.force_media = 1; } else { @@ -87542,7 +93212,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } bmcr = BMCR_ANENABLE | BMCR_ANRESTART; -@@ -5016,7 +6248,7 @@ static void rtl8153b_up(struct r8152 *tp) +@@ -5018,7 +6250,7 @@ static void rtl8153b_up(struct r8152 *tp) r8153_aldps_en(tp, true); @@ -87551,7 +93221,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 r8153b_u1u2en(tp, true); } -@@ -5041,239 +6273,486 @@ static void rtl8153b_down(struct r8152 *tp) +@@ -5043,239 +6275,486 @@ static void rtl8153b_down(struct r8152 *tp) r8153_aldps_en(tp, true); } @@ -88211,7 +93881,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 rtl_drop_queued_tx(tp); rtl_stop_rx(tp); } else { -@@ -5281,95 +6760,775 @@ static int rtl8152_close(struct net_device *netdev) +@@ -5283,95 +6762,775 @@ static int rtl8152_close(struct net_device *netdev) tp->rtl_ops.down(tp); @@ -89035,7 +94705,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 data = r8152_mdio_read(tp, MII_BMCR); if (data & BMCR_PDOWN) { -@@ -5377,119 +7536,450 @@ static void r8153_init(struct r8152 *tp) +@@ -5379,119 +7538,450 @@ static void r8153_init(struct r8152 *tp) r8152_mdio_write(tp, MII_BMCR, data); } @@ -89570,7 +95240,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 { u32 ocp_data; u16 data; -@@ -5498,8 +7988,31 @@ static void r8153b_init(struct r8152 *tp) +@@ -5500,8 +7990,31 @@ static void r8153b_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; @@ -89602,7 +95272,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 for (i = 0; i < 500; i++) { if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & AUTOLOAD_DONE) -@@ -5507,10 +8020,19 @@ static void r8153b_init(struct r8152 *tp) +@@ -5509,10 +8022,19 @@ static void r8153b_init(struct r8152 *tp) msleep(20); if (test_bit(RTL8152_UNPLUG, &tp->flags)) @@ -89623,7 +95293,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 data = r8152_mdio_read(tp, MII_BMCR); if (data & BMCR_PDOWN) { -@@ -5529,39 +8051,50 @@ static void r8153b_init(struct r8152 *tp) +@@ -5531,39 +8053,50 @@ static void r8153b_init(struct r8152 *tp) ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); r8153b_power_cut_en(tp, false); @@ -89696,7 +95366,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 set_bit(GREEN_ETHERNET, &tp->flags); -@@ -5575,6 +8108,39 @@ static void r8153b_init(struct r8152 *tp) +@@ -5577,6 +8110,39 @@ static void r8153b_init(struct r8152 *tp) tp->coalesce = 15000; /* 15 us */ } @@ -89736,7 +95406,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static int rtl8152_pre_reset(struct usb_interface *intf) { struct r8152 *tp = usb_get_intfdata(intf); -@@ -5725,6 +8291,9 @@ static int rtl8152_runtime_suspend(struct r8152 *tp) +@@ -5727,6 +8293,9 @@ static int rtl8152_runtime_suspend(struct r8152 *tp) struct net_device *netdev = tp->netdev; int ret = 0; @@ -89746,7 +95416,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 set_bit(SELECTIVE_SUSPEND, &tp->flags); smp_mb__after_atomic(); -@@ -5935,6 +8504,22 @@ int rtl8152_get_link_ksettings(struct net_device *netdev, +@@ -5937,6 +8506,22 @@ int rtl8152_get_link_ksettings(struct net_device *netdev, mii_ethtool_get_link_ksettings(&tp->mii, cmd); @@ -89769,7 +95439,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 mutex_unlock(&tp->control); usb_autopm_put_interface(tp->intf); -@@ -5978,6 +8563,10 @@ static int rtl8152_set_link_ksettings(struct net_device *dev, +@@ -5980,6 +8565,10 @@ static int rtl8152_set_link_ksettings(struct net_device *dev, cmd->link_modes.advertising)) advertising |= RTL_ADVERTISED_1000_FULL; @@ -89780,7 +95450,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 mutex_lock(&tp->control); ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed, -@@ -6124,6 +8713,11 @@ rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) +@@ -6126,6 +8715,11 @@ rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) struct r8152 *tp = netdev_priv(net); int ret; @@ -89792,7 +95462,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 ret = usb_autopm_get_interface(tp->intf); if (ret < 0) goto out; -@@ -6146,6 +8740,11 @@ rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) +@@ -6148,6 +8742,11 @@ rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) struct r8152 *tp = netdev_priv(net); int ret; @@ -89804,7 +95474,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 ret = usb_autopm_get_interface(tp->intf); if (ret < 0) goto out; -@@ -6430,12 +9029,21 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu) +@@ -6436,12 +9035,21 @@ static int rtl8152_change_mtu(struct net_device *dev, int new_mtu) dev->mtu = new_mtu; if (netif_running(dev)) { @@ -89831,7 +95501,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 } mutex_unlock(&tp->control); -@@ -6524,6 +9132,7 @@ static int rtl_ops_init(struct r8152 *tp) +@@ -6530,6 +9138,7 @@ static int rtl_ops_init(struct r8152 *tp) ops->in_nway = rtl8153_in_nway; ops->hw_phy_cfg = r8153_hw_phy_cfg; ops->autosuspend_en = rtl8153_runtime_enable; @@ -89839,7 +95509,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (tp->udev->speed < USB_SPEED_SUPER) tp->rx_buf_sz = 16 * 1024; else -@@ -6545,6 +9154,68 @@ static int rtl_ops_init(struct r8152 *tp) +@@ -6551,6 +9160,68 @@ static int rtl_ops_init(struct r8152 *tp) ops->in_nway = rtl8153_in_nway; ops->hw_phy_cfg = r8153b_hw_phy_cfg; ops->autosuspend_en = rtl8153b_runtime_enable; @@ -89908,7 +95578,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 tp->rx_buf_sz = 32 * 1024; tp->eee_en = true; tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX; -@@ -6552,7 +9223,7 @@ static int rtl_ops_init(struct r8152 *tp) +@@ -6558,7 +9229,7 @@ static int rtl_ops_init(struct r8152 *tp) default: ret = -ENODEV; @@ -89917,7 +95587,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 break; } -@@ -6563,11 +9234,17 @@ static int rtl_ops_init(struct r8152 *tp) +@@ -6569,11 +9240,17 @@ static int rtl_ops_init(struct r8152 *tp) #define FIRMWARE_8153A_3 "rtl_nic/rtl8153a-3.fw" #define FIRMWARE_8153A_4 "rtl_nic/rtl8153a-4.fw" #define FIRMWARE_8153B_2 "rtl_nic/rtl8153b-2.fw" @@ -89935,7 +95605,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 static int rtl_fw_init(struct r8152 *tp) { -@@ -6593,6 +9270,19 @@ static int rtl_fw_init(struct r8152 *tp) +@@ -6599,6 +9276,19 @@ static int rtl_fw_init(struct r8152 *tp) rtl_fw->pre_fw = r8153b_pre_firmware_1; rtl_fw->post_fw = r8153b_post_firmware_1; break; @@ -89955,7 +95625,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 default: break; } -@@ -6600,7 +9290,7 @@ static int rtl_fw_init(struct r8152 *tp) +@@ -6606,7 +9296,7 @@ static int rtl_fw_init(struct r8152 *tp) return 0; } @@ -89964,7 +95634,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 { struct usb_device *udev = interface_to_usbdev(intf); u32 ocp_data = 0; -@@ -6648,6 +9338,27 @@ static u8 rtl_get_version(struct usb_interface *intf) +@@ -6654,6 +9344,27 @@ static u8 rtl_get_version(struct usb_interface *intf) case 0x6010: version = RTL_VER_09; break; @@ -89992,7 +95662,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 default: version = RTL_VER_UNKNOWN; dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data); -@@ -6658,12 +9369,13 @@ static u8 rtl_get_version(struct usb_interface *intf) +@@ -6664,12 +9375,13 @@ static u8 rtl_get_version(struct usb_interface *intf) return version; } @@ -90007,7 +95677,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 struct r8152 *tp; struct net_device *netdev; int ret; -@@ -6671,10 +9383,8 @@ static int rtl8152_probe(struct usb_interface *intf, +@@ -6677,10 +9389,8 @@ static int rtl8152_probe(struct usb_interface *intf, if (version == RTL_VER_UNKNOWN) return -ENODEV; @@ -90019,7 +95689,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 if (intf->cur_altsetting->desc.bNumEndpoints < 3) return -ENODEV; -@@ -6715,7 +9425,7 @@ static int rtl8152_probe(struct usb_interface *intf, +@@ -6721,7 +9431,7 @@ static int rtl8152_probe(struct usb_interface *intf, mutex_init(&tp->control); INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); @@ -90028,7 +95698,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 tasklet_disable(&tp->tx_tl); netdev->netdev_ops = &rtl8152_netdev_ops; -@@ -6759,12 +9469,29 @@ static int rtl8152_probe(struct usb_interface *intf, +@@ -6765,12 +9475,29 @@ static int rtl8152_probe(struct usb_interface *intf, /* MTU range: 68 - 1500 or 9194 */ netdev->min_mtu = ETH_MIN_MTU; switch (tp->version) { @@ -90061,7 +95731,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 break; } -@@ -6780,7 +9507,13 @@ static int rtl8152_probe(struct usb_interface *intf, +@@ -6786,7 +9513,13 @@ static int rtl8152_probe(struct usb_interface *intf, tp->advertising = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL | RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL; if (tp->mii.supports_gmii) { @@ -90076,7 +95746,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 tp->advertising |= RTL_ADVERTISED_1000_FULL; } tp->duplex = DUPLEX_FULL; -@@ -6804,11 +9537,15 @@ static int rtl8152_probe(struct usb_interface *intf, +@@ -6810,11 +9543,15 @@ static int rtl8152_probe(struct usb_interface *intf, set_ethernet_addr(tp); usb_set_intfdata(intf, tp); @@ -90094,7 +95764,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 goto out1; } -@@ -6840,7 +9577,8 @@ static void rtl8152_disconnect(struct usb_interface *intf) +@@ -6846,7 +9583,8 @@ static void rtl8152_disconnect(struct usb_interface *intf) unregister_netdev(tp->netdev); tasklet_kill(&tp->tx_tl); cancel_delayed_work_sync(&tp->hw_phy_work); @@ -90104,7 +95774,7 @@ index 63b64fa7f33c..bf402dfd0c2c 100644 rtl8152_release_firmware(tp); free_netdev(tp->netdev); } -@@ -6860,13 +9598,28 @@ static void rtl8152_disconnect(struct usb_interface *intf) +@@ -6866,13 +9604,28 @@ static void rtl8152_disconnect(struct usb_interface *intf) .idProduct = (prod), \ .bInterfaceClass = USB_CLASS_COMM, \ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ @@ -90302,7 +95972,7 @@ index 000000000000..2c3fabd38b16 +MODULE_DESCRIPTION("Realtek USB ECM device"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index ea0d5f04dc3a..09d4c1963b2c 100644 +index 65d42f5d42a3..bd5ab236ca13 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -50,6 +50,7 @@ @@ -90332,7 +96002,7 @@ index ea0d5f04dc3a..09d4c1963b2c 100644 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -753,6 +766,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +@@ -763,6 +776,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return phy_mii_ioctl(netdev->phydev, rq, cmd); } @@ -90386,7 +96056,7 @@ index ea0d5f04dc3a..09d4c1963b2c 100644 static void smsc95xx_init_mac_address(struct usbnet *dev) { /* maybe the boot loader passed the MAC address in devicetree */ -@@ -775,6 +835,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) +@@ -785,6 +845,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } @@ -90397,7 +96067,7 @@ index ea0d5f04dc3a..09d4c1963b2c 100644 /* no useful static MAC address found. generate a random one */ eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -@@ -901,13 +965,13 @@ static int smsc95xx_reset(struct usbnet *dev) +@@ -911,13 +975,13 @@ static int smsc95xx_reset(struct usbnet *dev) if (!turbo_mode) { burst_cap = 0; @@ -90416,7 +96086,7 @@ index ea0d5f04dc3a..09d4c1963b2c 100644 } netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -@@ -1827,7 +1891,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1838,7 +1902,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ @@ -90426,7 +96096,7 @@ index ea0d5f04dc3a..09d4c1963b2c 100644 return 1; } -@@ -1845,7 +1910,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1856,7 +1921,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ @@ -90466,7 +96136,7 @@ index 3f5da3bb6aa5..ba3c58caac9f 100644 static inline diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index c2b6e5c966d0..e51b42b547be 100644 +index 300c63d75df2..923b7559efb6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -9,6 +9,7 @@ @@ -90494,7 +96164,7 @@ index c2b6e5c966d0..e51b42b547be 100644 err = brcmf_fil_iovar_int_set(ifp, "pm2_sleep_ret", min_t(u32, timeout, BRCMF_PS_MAX_TIMEOUT_MS)); if (err) -@@ -7356,12 +7358,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], +@@ -7361,12 +7363,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], struct brcmfmac_pd_cc *country_codes; struct brcmfmac_pd_cc_entry *cc; s32 found_index; @@ -90515,7 +96185,7 @@ index c2b6e5c966d0..e51b42b547be 100644 } if ((alpha2[0] == ccreq->country_abbrev[0]) && -@@ -7385,10 +7393,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], +@@ -7390,10 +7398,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], brcmf_dbg(TRACE, "No country code match found\n"); return -EINVAL; } @@ -90533,7 +96203,7 @@ index c2b6e5c966d0..e51b42b547be 100644 ccreq->country_abbrev[0] = alpha2[0]; ccreq->country_abbrev[1] = alpha2[1]; ccreq->country_abbrev[2] = 0; -@@ -7403,31 +7415,45 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, +@@ -7408,31 +7420,45 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); struct brcmf_pub *drvr = cfg->pub; struct brcmf_fil_country_le ccreq; @@ -90621,8 +96291,26 @@ index e3758bd86acf..9047a0813ebf 100644 if (err) { brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", err); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +index 4146faeed344..d7d0f84f3693 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +@@ -63,7 +63,12 @@ void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...); + #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) + + /* For debug/tracing purposes treat info messages as errors */ +-#define brcmf_info brcmf_err ++// #define brcmf_info brcmf_err ++ ++#define brcmf_info(fmt, ...) \ ++ do { \ ++ pr_info("%s: " fmt, __func__, ##__VA_ARGS__); \ ++ } while (0) + + __printf(3, 4) + void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c -index d821a4758f8c..b14963be17f1 100644 +index a2b8d9171af2..76c5c540a9a5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -10,6 +10,7 @@ @@ -90642,7 +96330,7 @@ index d821a4758f8c..b14963be17f1 100644 /** * struct nvram_parser - internal info for parser. * -@@ -545,10 +548,26 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) +@@ -547,10 +550,26 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) goto fail; } @@ -90670,7 +96358,7 @@ index d821a4758f8c..b14963be17f1 100644 if (free_bcm47xx_nvram) bcm47xx_nvram_release_contents(data); -@@ -613,7 +632,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw, +@@ -615,7 +634,7 @@ static int brcmf_fw_request_firmware(const struct firmware **fw, strlcat(alt_path, fwctx->req->board_type, BRCMF_FW_NAME_LEN); strlcat(alt_path, ".txt", BRCMF_FW_NAME_LEN); @@ -90679,11 +96367,83 @@ index d821a4758f8c..b14963be17f1 100644 if (ret == 0) return ret; } +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +index a7554265f95f..db4ac19f0800 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -10,6 +10,7 @@ + #include "debug.h" + #include "core.h" + #include "common.h" ++#include "firmware.h" + #include "of.h" + + void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, +@@ -65,3 +66,38 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + sdio->oob_irq_nr = irq; + sdio->oob_irq_flags = irqf; + } ++ ++struct brcmf_firmware_mapping * ++brcmf_of_fwnames(struct device *dev, u32 *fwname_count) ++{ ++ struct device_node *np = dev->of_node; ++ struct brcmf_firmware_mapping *fwnames; ++ struct device_node *map_np, *fw_np; ++ int of_count; ++ int count = 0; ++ ++ map_np = of_get_child_by_name(np, "firmwares"); ++ of_count = of_get_child_count(map_np); ++ if (!of_count) ++ return NULL; ++ ++ fwnames = devm_kcalloc(dev, of_count, ++ sizeof(struct brcmf_firmware_mapping), ++ GFP_KERNEL); ++ ++ for_each_child_of_node(map_np, fw_np) ++ { ++ struct brcmf_firmware_mapping *cur = &fwnames[count]; ++ ++ if (of_property_read_u32(fw_np, "chipid", &cur->chipid) || ++ of_property_read_u32(fw_np, "revmask", &cur->revmask)) ++ continue; ++ cur->fw_base = of_get_property(fw_np, "fw_base", NULL); ++ if (cur->fw_base) ++ count++; ++ } ++ ++ *fwname_count = count; ++ ++ return count ? fwnames : NULL; ++} +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h +index 10bf52253337..5b39a39812d0 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h +@@ -5,9 +5,16 @@ + #ifdef CONFIG_OF + void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings); ++struct brcmf_firmware_mapping * ++brcmf_of_fwnames(struct device *dev, u32 *map_count); + #else + static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) + { + } ++static struct brcmf_firmware_mapping * ++brcmf_of_fwnames(struct device *dev, u32 *map_count) ++{ ++ return NULL; ++} + #endif /* CONFIG_OF */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -index 1f12dfb33938..89cdd2075846 100644 +index 61febc9bfa14..7491710bdec0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -@@ -1400,7 +1400,8 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) +@@ -1372,7 +1372,8 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) } static @@ -90693,7 +96453,7 @@ index 1f12dfb33938..89cdd2075846 100644 { struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_fw_request *fwreq; -@@ -1408,6 +1409,10 @@ int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name) +@@ -1380,6 +1381,10 @@ int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name) { ext, fw_name }, }; @@ -90705,10 +96465,18 @@ index 1f12dfb33938..89cdd2075846 100644 brcmf_pcie_fwnames, ARRAY_SIZE(brcmf_pcie_fwnames), diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -index 6d5d5c39c635..3ab944c39677 100644 +index 9929e90866f0..5de2f21a3cfe 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -611,12 +611,14 @@ BRCMF_FW_DEF(4329, "brcmfmac4329-sdio"); +@@ -35,6 +35,7 @@ + #include "core.h" + #include "common.h" + #include "bcdc.h" ++#include "of.h" + + #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) + #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) +@@ -611,6 +612,7 @@ BRCMF_FW_DEF(4329, "brcmfmac4329-sdio"); BRCMF_FW_DEF(4330, "brcmfmac4330-sdio"); BRCMF_FW_DEF(4334, "brcmfmac4334-sdio"); BRCMF_FW_DEF(43340, "brcmfmac43340-sdio"); @@ -90716,14 +96484,16 @@ index 6d5d5c39c635..3ab944c39677 100644 BRCMF_FW_DEF(4335, "brcmfmac4335-sdio"); BRCMF_FW_DEF(43362, "brcmfmac43362-sdio"); BRCMF_FW_DEF(4339, "brcmfmac4339-sdio"); - BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio"); - /* Note the names are not postfixed with a1 for backward compatibility */ - BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio"); -+BRCMF_FW_DEF(43436, "brcmfmac43436-sdio"); - BRCMF_FW_DEF(43455, "brcmfmac43455-sdio"); - BRCMF_FW_DEF(43456, "brcmfmac43456-sdio"); - BRCMF_FW_DEF(4354, "brcmfmac4354-sdio"); -@@ -634,12 +636,13 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { +@@ -625,7 +627,7 @@ BRCMF_FW_DEF(4359, "brcmfmac4359-sdio"); + BRCMF_FW_DEF(4373, "brcmfmac4373-sdio"); + BRCMF_FW_DEF(43012, "brcmfmac43012-sdio"); + +-static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { ++static const struct brcmf_firmware_mapping sdio_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4), +@@ -634,7 +636,7 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), BRCMF_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), BRCMF_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), @@ -90732,14 +96502,17 @@ index 6d5d5c39c635..3ab944c39677 100644 BRCMF_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), - BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0), -- BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1), -+ BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFA, 43430A1), -+ BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000004, 43436), - BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0x00000200, 43456), - BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455), - BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), -@@ -4114,14 +4117,24 @@ brcmf_sdio_watchdog(struct timer_list *t) +@@ -649,6 +651,9 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { + BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012) + }; + ++static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames; ++static u32 brcmf_sdio_fwnames_count; ++ + #define TXCTL_CREDITS 2 + + static void pkt_align(struct sk_buff *p, int len, int align) +@@ -4114,17 +4119,27 @@ brcmf_sdio_watchdog(struct timer_list *t) } static @@ -90764,7 +96537,87 @@ index 6d5d5c39c635..3ab944c39677 100644 + } fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev, brcmf_sdio_fwnames, - ARRAY_SIZE(brcmf_sdio_fwnames), +- ARRAY_SIZE(brcmf_sdio_fwnames), ++ brcmf_sdio_fwnames_count, + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return -ENOMEM; +@@ -4180,6 +4195,9 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { + #define BRCMF_SDIO_FW_CODE 0 + #define BRCMF_SDIO_FW_NVRAM 1 + ++static struct brcmf_fw_request * ++brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus); ++ + static void brcmf_sdio_firmware_callback(struct device *dev, int err, + struct brcmf_fw_request *fwreq) + { +@@ -4195,6 +4213,22 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, + + brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); + ++ if (err && brcmf_sdio_fwnames != sdio_fwnames) { ++ /* Try again with the standard firmware names */ ++ brcmf_sdio_fwnames = sdio_fwnames; ++ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); ++ kfree(fwreq); ++ fwreq = brcmf_sdio_prepare_fw_request(bus); ++ if (!fwreq) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ err = brcmf_fw_get_firmwares(dev, fwreq, ++ brcmf_sdio_firmware_callback); ++ if (!err) ++ return; ++ } ++ + if (err) + goto fail; + +@@ -4402,7 +4436,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) + + fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, + brcmf_sdio_fwnames, +- ARRAY_SIZE(brcmf_sdio_fwnames), ++ brcmf_sdio_fwnames_count, + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return NULL; +@@ -4420,6 +4454,9 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + struct brcmf_sdio *bus; + struct workqueue_struct *wq; + struct brcmf_fw_request *fwreq; ++ struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL; ++ const int fwname_size = sizeof(struct brcmf_firmware_mapping); ++ u32 of_fw_count; + + brcmf_dbg(TRACE, "Enter\n"); + +@@ -4502,6 +4539,23 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) + + brcmf_dbg(INFO, "completed!!\n"); + ++ brcmf_sdio_fwnames = sdio_fwnames; ++ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); ++ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count); ++ if (of_fwnames) ++ fwnames = devm_kcalloc(sdiodev->dev, ++ of_fw_count + brcmf_sdio_fwnames_count, ++ fwname_size, GFP_KERNEL); ++ ++ if (fwnames) { ++ /* The array is scanned in order, so overrides come first */ ++ memcpy(fwnames, of_fwnames, of_fw_count * fwname_size); ++ memcpy(fwnames + of_fw_count, sdio_fwnames, ++ brcmf_sdio_fwnames_count * fwname_size); ++ brcmf_sdio_fwnames = fwnames; ++ brcmf_sdio_fwnames_count += of_fw_count; ++ } ++ + fwreq = brcmf_sdio_prepare_fw_request(bus); + if (!fwreq) { + ret = -ENOMEM; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 9fb68c2dc7e3..9bf2dbd30ded 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -91232,10 +97085,10 @@ index 000000000000..ac04301dabe1 +} +late_initcall(of_cfs_init); diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c -index 43a77d720008..bccef312f4c3 100644 +index c8a0c0e9dec1..7682daa65ba1 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c -@@ -245,6 +245,8 @@ static struct property *dup_and_fixup_symbol_prop( +@@ -243,6 +243,8 @@ static struct property *dup_and_fixup_symbol_prop( if (!target_path) return NULL; target_path_len = strlen(target_path); @@ -92010,10 +97863,10 @@ index 000000000000..5ae2bdaa88b4 +MODULE_LICENSE("GPL"); + diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 1d21129f7751..c5d88157f4b2 100644 +index 39d2024dc2ee..cd8a0d5596ed 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -362,7 +362,7 @@ static const struct gpio_chip bcm2835_gpio_chip = { +@@ -378,7 +378,7 @@ static const struct gpio_chip bcm2835_gpio_chip = { .get = bcm2835_gpio_get, .set = bcm2835_gpio_set, .set_config = gpiochip_generic_config, @@ -92021,8 +97874,8 @@ index 1d21129f7751..c5d88157f4b2 100644 + .base = 0, .ngpio = BCM2835_NUM_GPIOS, .can_sleep = false, - }; -@@ -378,7 +378,7 @@ static const struct gpio_chip bcm2711_gpio_chip = { + .of_gpio_ranges_fallback = bcm2835_of_gpio_ranges_fallback, +@@ -395,7 +395,7 @@ static const struct gpio_chip bcm2711_gpio_chip = { .get = bcm2835_gpio_get, .set = bcm2835_gpio_set, .set_config = gpiochip_generic_config, @@ -92030,39 +97883,8 @@ index 1d21129f7751..c5d88157f4b2 100644 + .base = 0, .ngpio = BCM2711_NUM_GPIOS, .can_sleep = false, - }; -@@ -1244,6 +1244,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) - raw_spin_lock_init(&pc->irq_lock[i]); - } - -+ pc->pctl_desc = *pdata->pctl_desc; -+ pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); -+ if (IS_ERR(pc->pctl_dev)) { -+ gpiochip_remove(&pc->gpio_chip); -+ return PTR_ERR(pc->pctl_dev); -+ } -+ -+ pc->gpio_range = *pdata->gpio_range; -+ pc->gpio_range.base = pc->gpio_chip.base; -+ pc->gpio_range.gc = &pc->gpio_chip; -+ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); -+ - girq = &pc->gpio_chip.irq; - girq->chip = &bcm2835_gpio_irq_chip; - girq->parent_handler = bcm2835_gpio_irq_handler; -@@ -1251,8 +1263,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) - girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, - sizeof(*girq->parents), - GFP_KERNEL); -- if (!girq->parents) -+ if (!girq->parents) { -+ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); - return -ENOMEM; -+ } - - if (is_7211) { - pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, -@@ -1274,9 +1288,13 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) + .of_gpio_ranges_fallback = bcm2835_of_gpio_ranges_fallback, +@@ -1308,9 +1308,13 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) char *name; girq->parents[i] = irq_of_parse_and_map(np, i); @@ -92078,7 +97900,7 @@ index 1d21129f7751..c5d88157f4b2 100644 /* Skip over the all banks interrupts */ pc->wake_irq[i] = irq_of_parse_and_map(np, i + BCM2835_NUM_IRQS + 1); -@@ -1300,24 +1318,13 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1336,7 +1340,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; @@ -92086,25 +97908,7 @@ index 1d21129f7751..c5d88157f4b2 100644 + err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc); if (err) { dev_err(dev, "could not add GPIO chip\n"); -+ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); - return err; - } - -- pc->pctl_desc = *pdata->pctl_desc; -- pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); -- if (IS_ERR(pc->pctl_dev)) { -- gpiochip_remove(&pc->gpio_chip); -- return PTR_ERR(pc->pctl_dev); -- } -- -- pc->gpio_range = *pdata->gpio_range; -- pc->gpio_range.base = pc->gpio_chip.base; -- pc->gpio_range.gc = &pc->gpio_chip; -- pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); -- - return 0; - } - + goto out_remove; diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index 1c5af2fef142..81e7acb8acb5 100644 --- a/drivers/power/reset/gpio-poweroff.c @@ -92442,7 +98246,7 @@ index e0de1df2ede0..ee7d8f4e7f2e 100644 } diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c -index ee46bfbf5eee..8090b9a485b5 100644 +index 991b4730d768..e3decc419814 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -8,6 +8,7 @@ @@ -92453,7 +98257,7 @@ index ee46bfbf5eee..8090b9a485b5 100644 #include #include #include -@@ -21,63 +22,146 @@ +@@ -21,87 +22,130 @@ /* I2C registers of the Atmel microcontroller. */ #define REG_ID 0x80 #define REG_PORTA 0x81 @@ -92517,28 +98321,40 @@ index ee46bfbf5eee..8090b9a485b5 100644 .cache_type = REGCACHE_NONE, }; +-static int attiny_lcd_power_enable(struct regulator_dev *rdev) +static int attiny_set_port_state(struct attiny_lcd *state, int reg, u8 val) -+{ + { +- unsigned int data; +- int ret, i; + state->port_states[reg - REG_PORTA] = val; + return regmap_write(state->regmap, reg, val); +}; -+ + +- regmap_write(rdev->regmap, REG_POWERON, 1); +- msleep(80); +static u8 attiny_get_port_state(struct attiny_lcd *state, int reg) +{ + return state->port_states[reg - REG_PORTA]; +}; -+ - static int attiny_lcd_power_enable(struct regulator_dev *rdev) - { -- unsigned int data; -+ struct attiny_lcd *state = rdev_get_drvdata(rdev); -- regmap_write(rdev->regmap, REG_POWERON, 1); - /* Wait for nPWRDWN to go low to indicate poweron is done. */ -- regmap_read_poll_timeout(rdev->regmap, REG_PORTB, data, -- data & BIT(0), 10, 1000000); -+ mutex_lock(&state->lock); +- for (i = 0; i < 20; i++) { +- ret = regmap_read(rdev->regmap, REG_PORTB, &data); +- if (!ret) { +- if (data & BIT(0)) +- break; +- } +- usleep_range(10000, 12000); +- } +- usleep_range(10000, 12000); ++static int attiny_lcd_power_enable(struct regulator_dev *rdev) ++{ ++ struct attiny_lcd *state = rdev_get_drvdata(rdev); + ++ mutex_lock(&state->lock); + +- if (ret) +- pr_err("%s: regmap_read_poll_timeout failed %d\n", __func__, ret); + /* Ensure bridge, and tp stay in reset */ + attiny_set_port_state(state, REG_PORTC, 0); + usleep_range(5000, 10000); @@ -92572,7 +98388,6 @@ index ee46bfbf5eee..8090b9a485b5 100644 + regmap_write(rdev->regmap, REG_PWM, 0); - regmap_write(rdev->regmap, REG_POWERON, 0); -- udelay(1); + usleep_range(5000, 10000); + + attiny_set_port_state(state, REG_PORTA, 0); @@ -92580,7 +98395,7 @@ index ee46bfbf5eee..8090b9a485b5 100644 + attiny_set_port_state(state, REG_PORTB, PB_LCD_VCC_N); + usleep_range(5000, 10000); + attiny_set_port_state(state, REG_PORTC, 0); -+ msleep(30); + msleep(30); + + mutex_unlock(&state->lock); + @@ -92589,37 +98404,38 @@ index ee46bfbf5eee..8090b9a485b5 100644 static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev) { -+ struct attiny_lcd *state = rdev_get_drvdata(rdev); - unsigned int data; -- int ret; -+ int ret, i; - -- ret = regmap_read(rdev->regmap, REG_POWERON, &data); +- unsigned int data; +- int ret, i; +- +- for (i = 0; i < 10; i++) { +- ret = regmap_read(rdev->regmap, REG_POWERON, &data); +- if (!ret) +- break; +- usleep_range(10000, 12000); +- } - if (ret < 0) - return ret; -+ mutex_lock(&state->lock); -+ -+ for (i = 0; i < 10; i++) { -+ ret = regmap_read(rdev->regmap, REG_PORTC, &data); -+ if (!ret) -+ break; -+ usleep_range(10000, 12000); -+ } - +- - if (!(data & BIT(0))) - return 0; -+ mutex_unlock(&state->lock); - -- ret = regmap_read(rdev->regmap, REG_PORTB, &data); - if (ret < 0) - return ret; ++ struct attiny_lcd *state = rdev_get_drvdata(rdev); +- for (i = 0; i < 10; i++) { +- ret = regmap_read(rdev->regmap, REG_PORTB, &data); +- if (!ret) +- break; +- usleep_range(10000, 12000); +- } +- +- if (ret < 0) +- return ret; +- - return data & BIT(0); -+ return data & PC_RST_BRIDGE_N; ++ return state->port_states[REG_PORTC - REG_PORTA] & PC_RST_BRIDGE_N; } static const struct regulator_init_data attiny_regulator_default = { -@@ -101,33 +185,71 @@ static const struct regulator_desc attiny_regulator = { +@@ -125,10 +169,13 @@ static const struct regulator_desc attiny_regulator = { static int attiny_update_status(struct backlight_device *bl) { @@ -92627,62 +98443,58 @@ index ee46bfbf5eee..8090b9a485b5 100644 + struct attiny_lcd *state = bl_get_data(bl); + struct regmap *regmap = state->regmap; int brightness = bl->props.brightness; -+ int ret, i; -+ -+ mutex_lock(&state->lock); + int ret, i; ++ mutex_lock(&state->lock); ++ if (bl->props.power != FB_BLANK_UNBLANK || bl->props.fb_blank != FB_BLANK_UNBLANK) brightness = 0; +@@ -139,30 +186,86 @@ static int attiny_update_status(struct backlight_device *bl) + break; + } -- return regmap_write(regmap, REG_PWM, brightness); --} -+ for (i = 0; i < 10; i++) { -+ ret = regmap_write(regmap, REG_PWM, brightness); -+ if (!ret) -+ break; -+ } - --static int attiny_get_brightness(struct backlight_device *bl) --{ -- struct regmap *regmap = bl_get_data(bl); -- int ret, brightness; + mutex_unlock(&state->lock); - -- ret = regmap_read(regmap, REG_PWM, &brightness); -- if (ret) -- return ret; -- -- return brightness; -+ return ret; ++ + return ret; } - static const struct backlight_ops attiny_bl = { - .update_status = attiny_update_status, -- .get_brightness = attiny_get_brightness, - }; - +-static int attiny_get_brightness(struct backlight_device *bl) ++static const struct backlight_ops attiny_bl = { ++ .update_status = attiny_update_status, ++}; ++ +static int attiny_gpio_get_direction(struct gpio_chip *gc, unsigned int off) +{ + return GPIO_LINE_DIRECTION_OUT; +} + +static void attiny_gpio_set(struct gpio_chip *gc, unsigned int off, int val) -+{ + { +- struct regmap *regmap = bl_get_data(bl); +- int ret, brightness, i; + struct attiny_lcd *state = gpiochip_get_data(gc); + u8 last_val; -+ + +- for (i = 0; i < 10; i++) { +- ret = regmap_read(regmap, REG_PWM, &brightness); +- if (!ret) +- break; +- } + if (off >= NUM_GPIO) + return; + + mutex_lock(&state->lock); -+ + +- if (ret) +- return ret; + last_val = attiny_get_port_state(state, mappings[off].reg); + if (val) + last_val |= mappings[off].mask; + else + last_val &= ~mappings[off].mask; -+ + +- return brightness; + attiny_set_port_state(state, mappings[off].reg, last_val); + + if (off == RST_BRIDGE_N && val) { @@ -92699,12 +98511,48 @@ index ee46bfbf5eee..8090b9a485b5 100644 + } + + mutex_unlock(&state->lock); -+} + } + +-static const struct backlight_ops attiny_bl = { +- .update_status = attiny_update_status, +- .get_brightness = attiny_get_brightness, +-}; ++static int attiny_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf) ++{ ++ struct i2c_msg msgs[1]; ++ u8 addr_buf[1] = { reg }; ++ u8 data_buf[1] = { 0, }; ++ int ret; + ++ /* Write register address */ ++ msgs[0].addr = client->addr; ++ msgs[0].flags = 0; ++ msgs[0].len = ARRAY_SIZE(addr_buf); ++ msgs[0].buf = addr_buf; ++ ++ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ if (ret != ARRAY_SIZE(msgs)) ++ return -EIO; ++ ++ usleep_range(5000, 10000); ++ ++ /* Read data from register */ ++ msgs[0].addr = client->addr; ++ msgs[0].flags = I2C_M_RD; ++ msgs[0].len = 1; ++ msgs[0].buf = data_buf; ++ ++ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ if (ret != ARRAY_SIZE(msgs)) ++ return -EIO; ++ ++ *buf = data_buf[0]; ++ return 0; ++} + /* * I2C driver interface functions - */ -@@ -138,22 +260,30 @@ static int attiny_i2c_probe(struct i2c_client *i2c, +@@ -174,22 +277,30 @@ static int attiny_i2c_probe(struct i2c_client *i2c, struct regulator_config config = { }; struct backlight_device *bl; struct regulator_dev *rdev; @@ -92729,7 +98577,8 @@ index ee46bfbf5eee..8090b9a485b5 100644 + goto error; } - ret = regmap_read(regmap, REG_ID, &data); +- ret = regmap_read(regmap, REG_ID, &data); ++ ret = attiny_i2c_read(i2c, REG_ID, &data); if (ret < 0) { dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret); - return ret; @@ -92737,7 +98586,7 @@ index ee46bfbf5eee..8090b9a485b5 100644 } switch (data) { -@@ -162,34 +292,73 @@ static int attiny_i2c_probe(struct i2c_client *i2c, +@@ -198,34 +309,73 @@ static int attiny_i2c_probe(struct i2c_client *i2c, break; default: dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data); @@ -92747,8 +98596,7 @@ index ee46bfbf5eee..8090b9a485b5 100644 } regmap_write(regmap, REG_POWERON, 0); -- mdelay(1); -+ msleep(30); + msleep(30); + regmap_write(regmap, REG_PWM, 0); config.dev = &i2c->dev; @@ -92819,7 +98667,7 @@ index ee46bfbf5eee..8090b9a485b5 100644 return 0; } -@@ -205,6 +374,7 @@ static struct i2c_driver attiny_regulator_driver = { +@@ -241,6 +391,7 @@ static struct i2c_driver attiny_regulator_driver = { .of_match_table = of_match_ptr(attiny_dt_ids), }, .probe = attiny_i2c_probe, @@ -93008,7 +98856,7 @@ index 1e0041ec8132..6059210170bc 100644 if (id != 0x62726467 /* "BRDG" */) { dev_err(dev, "ASB register ID returned 0x%08x\n", id); diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c -index 33c32e931767..0f6a2f7c8b53 100644 +index bb9d8386ba3b..417b37084551 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -28,6 +28,7 @@ @@ -93047,7 +98895,7 @@ index 33c32e931767..0f6a2f7c8b53 100644 /* set clock */ spi_hz = tfr->speed_hz; -@@ -1285,6 +1300,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev) +@@ -1289,6 +1304,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev) struct bcm2835_spi *bs; int err; @@ -93059,7 +98907,7 @@ index 33c32e931767..0f6a2f7c8b53 100644 ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs), dma_get_cache_alignment())); if (!ctlr) -@@ -1329,7 +1349,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev) +@@ -1333,7 +1353,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); @@ -93070,10 +98918,10 @@ index 33c32e931767..0f6a2f7c8b53 100644 if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c -index 8c261eac2cee..4436fd319df3 100644 +index 857a1399850c..7667278a0e74 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -3338,6 +3338,7 @@ static int __spi_validate_bits_per_word(struct spi_controller *ctlr, +@@ -3340,6 +3340,7 @@ static int __spi_validate_bits_per_word(struct spi_controller *ctlr, */ int spi_setup(struct spi_device *spi) { @@ -93081,7 +98929,7 @@ index 8c261eac2cee..4436fd319df3 100644 unsigned bad_bits, ugly_bits; int status; -@@ -3355,6 +3356,14 @@ int spi_setup(struct spi_device *spi) +@@ -3357,6 +3358,14 @@ int spi_setup(struct spi_device *spi) (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))) return -EINVAL; @@ -93197,7 +99045,7 @@ index 9670a8989b91..1a3219657cbb 100644 MODULE_DESCRIPTION("FB driver for the ST7735R LCD Controller"); MODULE_AUTHOR("Noralf Tronnes"); diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c -index 3a280cc1892c..af4e975e7b30 100644 +index 0a2dbed9ffc7..99258a8224dc 100644 --- a/drivers/staging/fbtft/fb_st7789v.c +++ b/drivers/staging/fbtft/fb_st7789v.c @@ -66,6 +66,12 @@ enum st7789v_command { @@ -93213,7 +99061,7 @@ index 3a280cc1892c..af4e975e7b30 100644 /** * init_display() - initialize the display controller * -@@ -145,6 +151,22 @@ static int init_display(struct fbtft_par *par) +@@ -147,6 +153,22 @@ static int init_display(struct fbtft_par *par) return 0; } @@ -93236,7 +99084,7 @@ index 3a280cc1892c..af4e975e7b30 100644 /** * set_var() - apply LCD properties like rotation and BGR mode * -@@ -155,20 +177,32 @@ static int init_display(struct fbtft_par *par) +@@ -157,20 +179,32 @@ static int init_display(struct fbtft_par *par) static int set_var(struct fbtft_par *par) { u8 madctl_par = 0; @@ -93269,7 +99117,7 @@ index 3a280cc1892c..af4e975e7b30 100644 break; default: return -EINVAL; -@@ -265,7 +299,16 @@ static struct fbtft_display display = { +@@ -267,7 +301,16 @@ static struct fbtft_display display = { }, }; @@ -93288,7 +99136,7 @@ index 3a280cc1892c..af4e975e7b30 100644 MODULE_ALIAS("spi:" DRVNAME); MODULE_ALIAS("platform:" DRVNAME); diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c -index 3723269890d5..6f4ad6e97637 100644 +index d0c8d85f3db0..39ecd7c7ec61 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -24,6 +24,8 @@ @@ -93300,7 +99148,7 @@ index 3723269890d5..6f4ad6e97637 100644 #include