]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
bcm27xx: import latest patches from the RPi foundation
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Thu, 18 Feb 2021 17:04:33 +0000 (18:04 +0100)
committerÁlvaro Fernández Rojas <noltari@gmail.com>
Thu, 18 Feb 2021 22:42:32 +0000 (23:42 +0100)
bcm2708: boot tested on RPi B+ v1.2
bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G
bcm2710: boot tested on RPi 3B v1.2
bcm2711: boot tested on RPi 4B v1.1 4G

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
924 files changed:
target/linux/bcm27xx/bcm2708/config-5.4
target/linux/bcm27xx/bcm2709/config-5.4
target/linux/bcm27xx/bcm2710/config-5.4
target/linux/bcm27xx/bcm2711/config-5.4
target/linux/bcm27xx/modules/sound.mk
target/linux/bcm27xx/patches-5.4/950-0134-spi-spi-bcm2835-Disable-forced-software-CS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0135-spi-spi-bcm2835-Disable-forced-software-CS.patch with 95% similarity]
target/linux/bcm27xx/patches-5.4/950-0134-spi-spi-bcm2835-Re-enable-HW-CS.patch [deleted file]
target/linux/bcm27xx/patches-5.4/950-0135-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch [moved from target/linux/bcm27xx/patches-5.4/950-0136-Added-driver-for-the-HiFiBerry-DAC-ADC-2694.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0136-configs-Enable-the-AD193x-codecs.patch [moved from target/linux/bcm27xx/patches-5.4/950-0137-configs-Enable-the-AD193x-codecs.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0137-lan78xx-EEE-support-is-now-a-PHY-property.patch [moved from target/linux/bcm27xx/patches-5.4/950-0138-lan78xx-EEE-support-is-now-a-PHY-property.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0138-Revert-staging-vchiq-delete-vchiq_killable.h.patch [moved from target/linux/bcm27xx/patches-5.4/950-0139-Revert-staging-vchiq-delete-vchiq_killable.h.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0139-Revert-staging-bcm2835-audio-Drop-DT-dependency.patch [moved from target/linux/bcm27xx/patches-5.4/950-0140-Revert-staging-bcm2835-audio-Drop-DT-dependency.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0140-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch [moved from target/linux/bcm27xx/patches-5.4/950-0141-gpu-vc4_firmware_kms-Fix-up-64-bit-compile-warnings.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0141-bcm2835-dma-Add-support-for-per-channel-flags.patch [moved from target/linux/bcm27xx/patches-5.4/950-0142-bcm2835-dma-Add-support-for-per-channel-flags.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0142-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0143-drm-vc4-Programming-the-CTM-is-conditional-on-runnin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0143-rtc-rv3028-Add-backup-switchover-mode-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0144-rtc-rv3028-Add-backup-switchover-mode-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0144-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0145-Audiophonics-I-Sabre-9038Q2M-DAC-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0145-lan78xx-use-default-alignment-for-rx-buffers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0146-lan78xx-use-default-alignment-for-rx-buffers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0146-Added-IQaudIO-Pi-Codec-board-support-2969.patch [moved from target/linux/bcm27xx/patches-5.4/950-0147-Added-IQaudIO-Pi-Codec-board-support-2969.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0147-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0148-sound-pcm512x-codec-Adding-352.8kHz-samplerate-suppo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0148-media-ov5647-Add-set_fmt-and-get_fmt-calls.patch [moved from target/linux/bcm27xx/patches-5.4/950-0149-media-ov5647-Add-set_fmt-and-get_fmt-calls.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0149-media-Documentation-DT-add-device-tree-for-PWDN-cont.patch [moved from target/linux/bcm27xx/patches-5.4/950-0150-media-Documentation-DT-add-device-tree-for-PWDN-cont.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0150-media-ov5647-Add-support-for-PWDN-GPIO.patch [moved from target/linux/bcm27xx/patches-5.4/950-0151-media-ov5647-Add-support-for-PWDN-GPIO.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0151-media-ov5647-Add-support-for-non-continuous-clock-mo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0152-media-ov5647-Add-support-for-non-continuous-clock-mo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0152-media-tc358743-Increase-FIFO-level-to-374.patch [moved from target/linux/bcm27xx/patches-5.4/950-0153-media-tc358743-Increase-FIFO-level-to-374.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0153-media-tc358743-fix-connected-active-CSI-2-lane-repor.patch [moved from target/linux/bcm27xx/patches-5.4/950-0154-media-tc358743-fix-connected-active-CSI-2-lane-repor.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0154-media-tc358743-Add-support-for-972Mbit-s-link-freq.patch [moved from target/linux/bcm27xx/patches-5.4/950-0155-media-tc358743-Add-support-for-972Mbit-s-link-freq.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0155-media-tc358743-Check-I2C-succeeded-during-probe.patch [moved from target/linux/bcm27xx/patches-5.4/950-0156-media-tc358743-Check-I2C-succeeded-during-probe.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0156-media-adv7180-Default-to-the-first-valid-input.patch [moved from target/linux/bcm27xx/patches-5.4/950-0157-media-adv7180-Default-to-the-first-valid-input.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0157-media-adv7180-Add-YPrPb-support-for-ADV7282M.patch [moved from target/linux/bcm27xx/patches-5.4/950-0158-media-adv7180-Add-YPrPb-support-for-ADV7282M.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0158-media-videodev2-Add-helper-defines-for-printing-FOUR.patch [moved from target/linux/bcm27xx/patches-5.4/950-0159-media-videodev2-Add-helper-defines-for-printing-FOUR.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0159-dt-bindings-Document-BCM283x-CSI2-CCP2-receiver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0160-dt-bindings-Document-BCM283x-CSI2-CCP2-receiver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0160-MAINTAINERS-Add-entry-for-BCM2835-Unicam-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0161-MAINTAINERS-Add-entry-for-BCM2835-Unicam-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0161-media-tc358743-Return-an-appropriate-colorspace-from.patch [moved from target/linux/bcm27xx/patches-5.4/950-0162-media-tc358743-Return-an-appropriate-colorspace-from.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0162-staging-bcm2835-camera-Fix-logical-continuation-spli.patch [moved from target/linux/bcm27xx/patches-5.4/950-0164-staging-bcm2835-camera-Fix-logical-continuation-spli.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0163-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch [moved from target/linux/bcm27xx/patches-5.4/950-0165-staging-bcm2835-camera-Ensure-timestamps-never-go-ba.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0164-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch [moved from target/linux/bcm27xx/patches-5.4/950-0166-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0165-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch [moved from target/linux/bcm27xx/patches-5.4/950-0167-staging-mmal-vchiq-Allocate-and-free-components-as-r.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0166-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch [moved from target/linux/bcm27xx/patches-5.4/950-0168-staging-mmal-vchiq-Avoid-use-of-bool-in-structures.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0167-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch [moved from target/linux/bcm27xx/patches-5.4/950-0169-staging-mmal-vchiq-Make-timeout-a-defined-parameter.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0168-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0170-staging-mmal-vchiq-Make-a-mmal_buf-struct-for-passin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0169-staging-mmal-vchiq-Add-support-for-event-callbacks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0171-staging-mmal-vchiq-Add-support-for-event-callbacks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0170-staging-vc04_services-Support-sending-data-to-MMAL-p.patch [moved from target/linux/bcm27xx/patches-5.4/950-0172-staging-vc04_services-Support-sending-data-to-MMAL-p.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0171-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch [moved from target/linux/bcm27xx/patches-5.4/950-0173-staging-vc04_services-Fixup-vchiq-mmal-include-order.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0172-staging-vc04_services-Add-new-vc-sm-cma-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0174-staging-vc04_services-Add-new-vc-sm-cma-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0173-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0175-staging-vc04_services-Use-vc-sm-cma-to-support-zero-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0174-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch [moved from target/linux/bcm27xx/patches-5.4/950-0176-media-videobuf2-Allow-exporting-of-a-struct-dmabuf.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0175-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0177-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0176-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch [moved from target/linux/bcm27xx/patches-5.4/950-0178-staging-mmal-vchiq-Fix-client_component-for-64-bit-k.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0177-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch [moved from target/linux/bcm27xx/patches-5.4/950-0179-clk-clk-bcm2835-Use-zd-when-printing-size_t.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0178-media-ov5647-Use-gpiod_set_value_cansleep.patch [moved from target/linux/bcm27xx/patches-5.4/950-0180-media-ov5647-Use-gpiod_set_value_cansleep.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0179-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch [moved from target/linux/bcm27xx/patches-5.4/950-0181-staging-bcm2835-codec-variable-vb2-may-be-used-unini.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0180-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0182-staging-bcm2835-codec-Fix-potentially-uninitialised-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0181-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch [moved from target/linux/bcm27xx/patches-5.4/950-0183-staging-mmal_vchiq-Add-in-the-Bayer-encoding-formats.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0182-staging-mmal-vchiq-Always-return-the-param-size-from.patch [moved from target/linux/bcm27xx/patches-5.4/950-0184-staging-mmal-vchiq-Always-return-the-param-size-from.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0183-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch [moved from target/linux/bcm27xx/patches-5.4/950-0185-staging-mmal-vchiq-If-the-VPU-returns-an-error-don-t.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch [moved from target/linux/bcm27xx/patches-5.4/950-0186-staging-bcm2835_codec-Query-supported-formats-from-t.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0185-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0187-staging-bcm2835_codec-Add-support-for-the-ISP-as-an-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0186-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0188-staging-bcm2835_codec-Add-an-option-for-ignoring-Bay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0187-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch [moved from target/linux/bcm27xx/patches-5.4/950-0189-staging-bcm2835_codec-Fix-handling-of-VB2_MEMORY_DMA.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0188-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch [moved from target/linux/bcm27xx/patches-5.4/950-0190-staging-mmal-vchiq-Update-mmal_parameters.h-with-rec.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0189-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch [moved from target/linux/bcm27xx/patches-5.4/950-0191-staging-bcm2835_codec-Include-timing-info-in-SPS-hea.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0190-staging-bcm2835-codec-NULL-component-handle-on-queue.patch [moved from target/linux/bcm27xx/patches-5.4/950-0192-staging-bcm2835-codec-NULL-component-handle-on-queue.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0191-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0193-staging-bcm2835_codec-Clean-up-logging-on-unloading-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0192-staging-bcm2835-codec-Refactor-default-resolution-co.patch [moved from target/linux/bcm27xx/patches-5.4/950-0194-staging-bcm2835-codec-Refactor-default-resolution-co.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0193-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch [moved from target/linux/bcm27xx/patches-5.4/950-0195-staging-bcm2835-codec-Correct-port-width-calc-for-tr.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0194-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0196-staging-bcm2835-codec-Remove-height-padding-for-ISP-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0195-staging-mmal-vchiq-Free-the-event-context-for-contro.patch [moved from target/linux/bcm27xx/patches-5.4/950-0197-staging-mmal-vchiq-Free-the-event-context-for-contro.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0196-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch [moved from target/linux/bcm27xx/patches-5.4/950-0198-staging-mmal-vchiq-Fix-memory-leak-in-error-path.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0197-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch [moved from target/linux/bcm27xx/patches-5.4/950-0200-staging-bcm2835-codec-Convert-V4L2-nsec-timestamps-t.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0198-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch [moved from target/linux/bcm27xx/patches-5.4/950-0201-staging-bcm2835-codec-Add-support-for-setting-S_PARM.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0199-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch [deleted file]
target/linux/bcm27xx/patches-5.4/950-0199-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch [moved from target/linux/bcm27xx/patches-5.4/950-0202-w1-w1-gpio-Make-GPIO-an-output-for-strong-pullup.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0200-arm-bcm2835-Fix-FIQ-early-ioremap.patch [moved from target/linux/bcm27xx/patches-5.4/950-0203-arm-bcm2835-Fix-FIQ-early-ioremap.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0201-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch [moved from target/linux/bcm27xx/patches-5.4/950-0204-Fix-copy_from_user-if-BCM2835_FAST_MEMCPY-n.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0202-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch [moved from target/linux/bcm27xx/patches-5.4/950-0205-dt-bindings-pci-Add-DT-docs-for-Brcmstb-PCIe-device.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0203-arm-bcm2835-DMA-can-only-address-1GB.patch [moved from target/linux/bcm27xx/patches-5.4/950-0206-arm-bcm2835-DMA-can-only-address-1GB.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0204-hwrng-iproc-rng200-Add-BCM2838-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0207-hwrng-iproc-rng200-Add-BCM2838-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0205-vchiq-Add-36-bit-address-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0208-vchiq-Add-36-bit-address-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0206-bcm2835-pcm.c-Support-multichannel-audio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0209-bcm2835-pcm.c-Support-multichannel-audio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0207-bcmgenet-constrain-max-DMA-burst-length.patch [moved from target/linux/bcm27xx/patches-5.4/950-0210-bcmgenet-constrain-max-DMA-burst-length.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0208-bcmgenet-Better-coalescing-parameter-defaults.patch [moved from target/linux/bcm27xx/patches-5.4/950-0211-bcmgenet-Better-coalescing-parameter-defaults.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0209-net-genet-enable-link-energy-detect-powerdown-for-ex.patch [moved from target/linux/bcm27xx/patches-5.4/950-0212-net-genet-enable-link-energy-detect-powerdown-for-ex.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0210-usb-xhci-Disable-the-XHCI-5-second-timeout.patch [moved from target/linux/bcm27xx/patches-5.4/950-0213-usb-xhci-Disable-the-XHCI-5-second-timeout.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0211-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch [moved from target/linux/bcm27xx/patches-5.4/950-0214-usb-xhci-Show-that-the-VIA-VL805-supports-LPM.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0212-spi-bcm2835-enable-shared-interrupt-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0215-spi-bcm2835-enable-shared-interrupt-support.patch with 95% similarity]
target/linux/bcm27xx/patches-5.4/950-0213-clk-bcm2835-Don-t-wait-for-pllh-lock.patch [moved from target/linux/bcm27xx/patches-5.4/950-0216-clk-bcm2835-Don-t-wait-for-pllh-lock.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0214-soc-bcm-bcm2835-pm-Add-support-for-2711.patch [moved from target/linux/bcm27xx/patches-5.4/950-0217-soc-bcm-bcm2835-pm-Add-support-for-2711.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0215-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch [moved from target/linux/bcm27xx/patches-5.4/950-0218-config-Permit-LPAE-and-PCIE_BRCMSTB-on-BCM2835.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0216-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch [moved from target/linux/bcm27xx/patches-5.4/950-0219-clk-bcm2835-Add-support-for-setting-leaf-clock-rates.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0217-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch [moved from target/linux/bcm27xx/patches-5.4/950-0220-clk-bcm2835-Allow-reparenting-leaf-clocks-while-they.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0218-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch [moved from target/linux/bcm27xx/patches-5.4/950-0221-usb-add-plumbing-for-updating-interrupt-endpoint-int.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0219-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch [moved from target/linux/bcm27xx/patches-5.4/950-0222-xhci-implement-xhci_fixup_endpoint-for-interval-adju.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0220-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch [moved from target/linux/bcm27xx/patches-5.4/950-0223-usbhid-call-usb_fixup_endpoint-after-mangling-interv.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0221-arm-bcm2835-Add-bcm2838-compatible-string.patch [moved from target/linux/bcm27xx/patches-5.4/950-0224-arm-bcm2835-Add-bcm2838-compatible-string.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0222-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch [moved from target/linux/bcm27xx/patches-5.4/950-0225-drm-vc4-Fix-oops-at-boot-with-firmwarekms-on-4.19.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0223-drm-v3d-Add-support-for-2711.patch [moved from target/linux/bcm27xx/patches-5.4/950-0226-drm-v3d-Add-support-for-2711.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0224-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch [moved from target/linux/bcm27xx/patches-5.4/950-0227-drm-v3d-Skip-MMU-flush-if-the-device-is-currently-of.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0225-drm-v3d-Hook-up-the-runtime-PM-ops.patch [moved from target/linux/bcm27xx/patches-5.4/950-0228-drm-v3d-Hook-up-the-runtime-PM-ops.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0226-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch [moved from target/linux/bcm27xx/patches-5.4/950-0229-drm-vc4-Fix-synchronization-firmwarekms-against-GL-r.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0227-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0230-drm-vc4-Expose-the-format-modifiers-for-firmware-kms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0228-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0231-drm-vc4-Fix-vblank-timestamping-for-firmwarekms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0229-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch [moved from target/linux/bcm27xx/patches-5.4/950-0232-gpu-vc4-fkms-Switch-to-the-newer-mailbox-frame-buffe.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0230-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0233-drm-vc4-Add-an-overlay-plane-to-vc4-firmware-kms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0231-drm-vc4-Increase-max-screen-size-to-4096x4096.patch [moved from target/linux/bcm27xx/patches-5.4/950-0234-drm-vc4-Increase-max-screen-size-to-4096x4096.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0232-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0235-drm-vc4-Add-support-for-multiple-displays-to-fkms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0233-drm-vc4-Fix-build-warning.patch [moved from target/linux/bcm27xx/patches-5.4/950-0236-drm-vc4-Fix-build-warning.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0234-drm-vc4-Select-display-to-blank-during-initialisatio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0237-drm-vc4-Select-display-to-blank-during-initialisatio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0235-drm-vc4-Remove-now-unused-structure.patch [moved from target/linux/bcm27xx/patches-5.4/950-0238-drm-vc4-Remove-now-unused-structure.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0236-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch [moved from target/linux/bcm27xx/patches-5.4/950-0239-drm-vc4-Query-the-display-ID-for-each-display-in-FKM.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0237-drm-vc4-Set-the-display-number-when-querying-the-dis.patch [moved from target/linux/bcm27xx/patches-5.4/950-0240-drm-vc4-Set-the-display-number-when-querying-the-dis.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0238-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch [moved from target/linux/bcm27xx/patches-5.4/950-0241-drm-vc4-Need-to-call-drm_crtc_vblank_-on-off-from-vc.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0239-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0242-drm-vc4-Add-support-for-H-V-flips-on-each-plane-for-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0240-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch [moved from target/linux/bcm27xx/patches-5.4/950-0243-drm-vc4-Remove-unused-vc4_fkms_cancel_page_flip-func.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0241-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0244-drm-vc4-Iterate-over-all-planes-in-vc4_crtc_-dis-en-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0242-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch [moved from target/linux/bcm27xx/patches-5.4/950-0245-drm-vc4-Bring-fkms-into-line-with-kms-in-blocking-do.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0243-drm-vc4-Increase-max_width-height-to-7680.patch [moved from target/linux/bcm27xx/patches-5.4/950-0246-drm-vc4-Increase-max_width-height-to-7680.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0244-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch [moved from target/linux/bcm27xx/patches-5.4/950-0247-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0245-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0248-drm-vc4-firmware-kms-Remove-incorrect-overscan-suppo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0246-drm-vc4-Log-flags-in-fkms-mode-set.patch [moved from target/linux/bcm27xx/patches-5.4/950-0249-drm-vc4-Log-flags-in-fkms-mode-set.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0247-drm-vc4-firmware-kms-Fix-DSI-display-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0250-drm-vc4-firmware-kms-Fix-DSI-display-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0248-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch [moved from target/linux/bcm27xx/patches-5.4/950-0251-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0249-drm-vc4-handle-the-case-where-there-are-no-available.patch [moved from target/linux/bcm27xx/patches-5.4/950-0252-drm-vc4-handle-the-case-where-there-are-no-available.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0250-drm-vc4-Support-the-VEC-in-FKMS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0253-drm-vc4-Support-the-VEC-in-FKMS.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0251-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0254-drm-vc4-Fixup-typo-when-setting-HDMI-aspect-ratio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0252-drm-vc4-Correct-SAND-support-for-FKMS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0255-drm-vc4-Correct-SAND-support-for-FKMS.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0253-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch [moved from target/linux/bcm27xx/patches-5.4/950-0256-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0254-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch [moved from target/linux/bcm27xx/patches-5.4/950-0257-drm-vc4-Max-resolution-of-7680-is-conditional-on-bei.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0255-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0258-drm-vc4-Fix-T-format-modifiers-in-FKMS.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0256-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch [moved from target/linux/bcm27xx/patches-5.4/950-0259-drm-vc4-Remove-340MHz-clock-limit-from-FKMS-now-scra.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0257-drm-vc4-Add-status-of-which-display-is-updated-throu.patch [moved from target/linux/bcm27xx/patches-5.4/950-0260-drm-vc4-Add-status-of-which-display-is-updated-throu.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0258-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-In-FKMS-look-at-the-modifiers-correctly-for-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0259-drm-vc4-Limit-fkms-to-modes-85Hz.patch [moved from target/linux/bcm27xx/patches-5.4/950-0262-drm-vc4-Limit-fkms-to-modes-85Hz.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0260-drm-vc4-Ignore-HVS-unless-initialised.patch [moved from target/linux/bcm27xx/patches-5.4/950-0263-drm-vc4-Ignore-HVS-unless-initialised.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch [moved from target/linux/bcm27xx/patches-5.4/950-0264-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0262-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch [moved from target/linux/bcm27xx/patches-5.4/950-0265-drm-vc4-Add-support-for-color-encoding-on-YUV-planes.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0263-tty-amba-pl011-Make-TX-optimisation-conditional.patch [moved from target/linux/bcm27xx/patches-5.4/950-0266-tty-amba-pl011-Make-TX-optimisation-conditional.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0264-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch [moved from target/linux/bcm27xx/patches-5.4/950-0267-xhci-add-quirk-for-host-controllers-that-don-t-updat.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0265-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0268-i2c-bcm2835-Set-clock-stretch-timeout-to-35ms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0266-staging-vc04_services-fix-compiling-in-separate-dire.patch [moved from target/linux/bcm27xx/patches-5.4/950-0269-staging-vc04_services-fix-compiling-in-separate-dire.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0267-clk-bcm2835-Avoid-null-pointer-exception.patch [moved from target/linux/bcm27xx/patches-5.4/950-0270-clk-bcm2835-Avoid-null-pointer-exception.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0268-drm-vc4-Prevent-load-tracking-from-breaking-FKMS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0271-drm-vc4-Prevent-load-tracking-from-breaking-FKMS.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0269-drm-v3d-HACK-gut-runtime-pm-for-now.patch [moved from target/linux/bcm27xx/patches-5.4/950-0272-drm-v3d-HACK-gut-runtime-pm-for-now.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0270-drm-v3d-Clock-V3D-down-when-not-in-use.patch [moved from target/linux/bcm27xx/patches-5.4/950-0273-drm-v3d-Clock-V3D-down-when-not-in-use.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0271-According-to-5713-pdf-doc-CLOCK_CTRL-is-a-readonly-s.patch [moved from target/linux/bcm27xx/patches-5.4/950-0274-According-to-5713-pdf-doc-CLOCK_CTRL-is-a-readonly-s.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0272-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch [moved from target/linux/bcm27xx/patches-5.4/950-0275-drm-vc4-Query-firmware-for-custom-HDMI-mode.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0273-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch [moved from target/linux/bcm27xx/patches-5.4/950-0276-drm-vc4-Pass-the-drm-vrefresh-to-the-firmware-on-mod.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0274-drm-vc4-Add-support-for-margins-to-fkms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0277-drm-vc4-Add-support-for-margins-to-fkms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0275-drm-vc4-Ensure-zpos-is-always-initialised.patch [moved from target/linux/bcm27xx/patches-5.4/950-0278-drm-vc4-Ensure-zpos-is-always-initialised.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0276-adds-the-Hifiberry-DAC-ADC-PRO-version.patch [moved from target/linux/bcm27xx/patches-5.4/950-0279-adds-the-Hifiberry-DAC-ADC-PRO-version.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0277-drm-vc4-A-present-but-empty-dmas-disables-audio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0280-drm-vc4-A-present-but-empty-dmas-disables-audio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0278-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch [moved from target/linux/bcm27xx/patches-5.4/950-0281-Fixup-FKMS-interrupt-handing-for-non-existent-displa.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0279-drivers-char-add-chardev-for-mmap-ing-the-RPiVid-con.patch [moved from target/linux/bcm27xx/patches-5.4/950-0282-drivers-char-add-chardev-for-mmap-ing-the-RPiVid-con.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0280-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch [moved from target/linux/bcm27xx/patches-5.4/950-0283-hid-usb-Add-device-quirks-for-Freeway-Airmouse-T3-an.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0281-drm-vc4-Add-Broadcast-RGB-connector-property.patch [moved from target/linux/bcm27xx/patches-5.4/950-0284-drm-vc4-Add-Broadcast-RGB-connector-property.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0282-drm-vc4-fkms-Set-default-state-margin-at-reset.patch [moved from target/linux/bcm27xx/patches-5.4/950-0285-drm-vc4-fkms-Set-default-state-margin-at-reset.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0283-staging-bcm2835-codec-switch-to-multi-planar-API.patch [moved from target/linux/bcm27xx/patches-5.4/950-0286-staging-bcm2835-codec-switch-to-multi-planar-API.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0284-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0287-staging-bcm2835-codec-implement-V4L2_CID_MIN_BUFFERS.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0285-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch [moved from target/linux/bcm27xx/patches-5.4/950-0288-staging-bcm2835-codec-set-device_caps-in-struct-vide.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0286-Add-HDMI1-facility-to-the-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0289-Add-HDMI1-facility-to-the-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0287-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0290-drm-vc4-Resolve-the-vblank-warnings-on-mode-switchin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0288-drm-vc4-Remove-unused-mode-variable.patch [moved from target/linux/bcm27xx/patches-5.4/950-0291-drm-vc4-Remove-unused-mode-variable.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0289-staging-bcm2835-codec-Expand-logging-on-format-setti.patch [moved from target/linux/bcm27xx/patches-5.4/950-0292-staging-bcm2835-codec-Expand-logging-on-format-setti.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0290-staging-bcm2835-codec-Correct-bytesperline-on-format.patch [moved from target/linux/bcm27xx/patches-5.4/950-0293-staging-bcm2835-codec-Correct-bytesperline-on-format.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0291-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch [moved from target/linux/bcm27xx/patches-5.4/950-0294-drm-vc4-Add-missing-NULL-check-to-vc4_crtc_consume_e.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0292-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch [moved from target/linux/bcm27xx/patches-5.4/950-0295-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0293-xhci-Use-more-event-ring-segment-table-entries.patch [moved from target/linux/bcm27xx/patches-5.4/950-0296-xhci-Use-more-event-ring-segment-table-entries.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0294-configs-arm64-bcm2711-Enable-V3D.patch [moved from target/linux/bcm27xx/patches-5.4/950-0297-configs-arm64-bcm2711-Enable-V3D.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0295-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch [moved from target/linux/bcm27xx/patches-5.4/950-0298-staging-bcm2835-codec-add-support-for-V4L2_CID_MPEG_.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0296-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0299-staging-bcm2835-codec-remove-unnecessary-padding-on-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0297-arch-arm-Add-model-string-to-cpuinfo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0300-arch-arm-Add-model-string-to-cpuinfo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0298-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0301-arch-arm64-Add-Revision-Serial-Model-to-cpuinfo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0299-staging-bcm2835-codec-Fix-non-documentation-comment-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0302-staging-bcm2835-codec-Fix-non-documentation-comment-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0300-staging-bcm2835-codec-Fix-declaration-of-roles.patch [moved from target/linux/bcm27xx/patches-5.4/950-0303-staging-bcm2835-codec-Fix-declaration-of-roles.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0301-staging-bcm2835-codec-Add-role-to-device-name.patch [moved from target/linux/bcm27xx/patches-5.4/950-0304-staging-bcm2835-codec-Add-role-to-device-name.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0302-staging-bcm2835-codec-Pass-driver-context-to-create-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0305-staging-bcm2835-codec-Pass-driver-context-to-create-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0303-staging-bcm2835-codec-add-media-controller-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0306-staging-bcm2835-codec-add-media-controller-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0304-v4l2-Add-a-Greyworld-AWB-mode.patch [moved from target/linux/bcm27xx/patches-5.4/950-0307-v4l2-Add-a-Greyworld-AWB-mode.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0305-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch [moved from target/linux/bcm27xx/patches-5.4/950-0308-staging-bcm2835-camera-Add-greyworld-AWB-mode.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0306-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch [moved from target/linux/bcm27xx/patches-5.4/950-0309-drm-vc4-Fix-for-margins-in-composite-SDTV-mode-3223.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0307-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch [moved from target/linux/bcm27xx/patches-5.4/950-0310-Add-Hifiberry-DAC-DSP-soundcard-driver-3224.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0308-staging-bcm2835-codec-Allow-height-of-1920.patch [moved from target/linux/bcm27xx/patches-5.4/950-0311-staging-bcm2835-codec-Allow-height-of-1920.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0309-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch [moved from target/linux/bcm27xx/patches-5.4/950-0312-staging-bcm2835-codec-Correct-g-s_selection-API-MPLA.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0310-drm-v3d-Delete-pm_runtime-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0313-drm-v3d-Delete-pm_runtime-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0311-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch [moved from target/linux/bcm27xx/patches-5.4/950-0314-dts-Add-DTS-for-Pi-2B-rev-1.2-with-BCM2837-3235.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0312-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch [moved from target/linux/bcm27xx/patches-5.4/950-0315-drm-v3d-clean-caches-at-the-end-of-render-jobs-on-re.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0313-kbuild-Allow-.dtbo-overlays-to-be-built-piecemeal.patch [moved from target/linux/bcm27xx/patches-5.4/950-0316-kbuild-Allow-.dtbo-overlays-to-be-built-piecemeal.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0314-dma-direct-Temporary-DMA-fix-on-arm64.patch [moved from target/linux/bcm27xx/patches-5.4/950-0317-dma-direct-Temporary-DMA-fix-on-arm64.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0315-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch [moved from target/linux/bcm27xx/patches-5.4/950-0318-ARM-bcm-Switch-board-clk-and-pinctrl-to-bcm2711-comp.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0316-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch [moved from target/linux/bcm27xx/patches-5.4/950-0319-pinctrl-bcm2835-Add-support-for-BCM2711-pull-up-func.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0317-vchiq_2835_arm-suppress-warning.patch [moved from target/linux/bcm27xx/patches-5.4/950-0320-vchiq_2835_arm-suppress-warning.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0318-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch [moved from target/linux/bcm27xx/patches-5.4/950-0321-Rename-HDMI-ALSA-device-names-check-for-enable-state.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0319-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch [moved from target/linux/bcm27xx/patches-5.4/950-0322-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0320-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch [moved from target/linux/bcm27xx/patches-5.4/950-0323-drm-vc4-Correct-handling-of-rotation-parameter-in-fk.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0321-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch [moved from target/linux/bcm27xx/patches-5.4/950-0324-dt-bindings-Add-binding-for-the-Infineon-IRS1125-sen.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0322-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch [moved from target/linux/bcm27xx/patches-5.4/950-0325-media-i2c-Add-a-driver-for-the-Infineon-IRS1125-dept.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0323-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch [moved from target/linux/bcm27xx/patches-5.4/950-0326-staging-bcm2835-codec-Add-support-for-ENUM_FRAMESIZE.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0324-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch [moved from target/linux/bcm27xx/patches-5.4/950-0327-staging-bcm2835-codec-Correct-buffer-type-check-on-G.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0325-staging-bcm2835-codec-Set-default-and-error-check-ti.patch [moved from target/linux/bcm27xx/patches-5.4/950-0328-staging-bcm2835-codec-Set-default-and-error-check-ti.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0326-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch [moved from target/linux/bcm27xx/patches-5.4/950-0329-staging-bcm2835-codec-Fix-imbalance-in-dma_buf_get-d.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0327-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch [moved from target/linux/bcm27xx/patches-5.4/950-0330-drm-vc4-Added-calls-for-firmware-display-blank-unbla.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0328-Revert-pinctrl-bcm2835-Pass-irqchip-when-adding-gpio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0331-Revert-pinctrl-bcm2835-Pass-irqchip-when-adding-gpio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0329-drm-v3d-Don-t-clear-MMU-control-bits-on-exception.patch [moved from target/linux/bcm27xx/patches-5.4/950-0332-drm-v3d-Don-t-clear-MMU-control-bits-on-exception.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0330-drm-v3d-Suppress-all-but-the-first-MMU-error.patch [moved from target/linux/bcm27xx/patches-5.4/950-0333-drm-v3d-Suppress-all-but-the-first-MMU-error.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0331-drm-v3d-Plug-dma_fence-leak.patch [moved from target/linux/bcm27xx/patches-5.4/950-0334-drm-v3d-Plug-dma_fence-leak.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0332-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch [moved from target/linux/bcm27xx/patches-5.4/950-0335-staging-vchiq_arm-Register-vcsm-cma-as-a-platform-dr.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0333-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0336-staging-vchiq_arm-Register-bcm2835-codec-as-a-platfo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0334-staging-bcm2835-codec-Fix-potential-memory-leak-of-i.patch [moved from target/linux/bcm27xx/patches-5.4/950-0337-staging-bcm2835-codec-Fix-potential-memory-leak-of-i.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0335-net-bcmgenet-The-second-IRQ-is-optional.patch [moved from target/linux/bcm27xx/patches-5.4/950-0339-net-bcmgenet-The-second-IRQ-is-optional.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0336-drm-v3d-The-third-IRQ-is-optional.patch [moved from target/linux/bcm27xx/patches-5.4/950-0340-drm-v3d-The-third-IRQ-is-optional.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0337-dwc_otg-Declare-DMA-capability-with-HCD_DMA-flag.patch [moved from target/linux/bcm27xx/patches-5.4/950-0341-dwc_otg-Declare-DMA-capability-with-HCD_DMA-flag.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0338-rpi-poe-fan-fix-def_pwm1-writes.patch [moved from target/linux/bcm27xx/patches-5.4/950-0342-rpi-poe-fan-fix-def_pwm1-writes.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0339-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch [moved from target/linux/bcm27xx/patches-5.4/950-0343-net-phy-2711-Allow-ethernet-LED-mode-to-be-set-via-d.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0340-overlays-smi-fix-typo-in-comment-3320.patch [moved from target/linux/bcm27xx/patches-5.4/950-0344-overlays-smi-fix-typo-in-comment-3320.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0341-net-phy-2711-Change-the-default-ethernet-LED-actions.patch [moved from target/linux/bcm27xx/patches-5.4/950-0345-net-phy-2711-Change-the-default-ethernet-LED-actions.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0342-overlays-Add-apds9960-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0346-overlays-Add-apds9960-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0343-overlays-Remove-hack-from-uart0-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0347-overlays-Remove-hack-from-uart0-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0344-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch [moved from target/linux/bcm27xx/patches-5.4/950-0348-arm-dts-overlays-pitft35-resistive-add-upstream-comp.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0345-v3d_drv-Handle-missing-clock-more-gracefully.patch [moved from target/linux/bcm27xx/patches-5.4/950-0349-v3d_drv-Handle-missing-clock-more-gracefully.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0346-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0350-v3d_gem-Kick-the-clock-so-firmware-knows-we-are-usin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0347-clk-bcm2835-Disable-v3d-clock.patch [moved from target/linux/bcm27xx/patches-5.4/950-0351-clk-bcm2835-Disable-v3d-clock.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0348-arm-dts-Correct-Pi-4B-LED-values.patch [moved from target/linux/bcm27xx/patches-5.4/950-0353-arm-dts-Correct-Pi-4B-LED-values.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0349-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch [moved from target/linux/bcm27xx/patches-5.4/950-0354-drm-v3d-Set-dma_mask-as-well-as-coherent_dma_mask.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0350-arm-dts-2711-Add-pcie0-alias.patch [moved from target/linux/bcm27xx/patches-5.4/950-0355-arm-dts-2711-Add-pcie0-alias.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0351-rpi-cirrus-wm5102-overlay-fix-pinctrl-configuration.patch [moved from target/linux/bcm27xx/patches-5.4/950-0356-rpi-cirrus-wm5102-overlay-fix-pinctrl-configuration.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0352-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch [deleted file]
target/linux/bcm27xx/patches-5.4/950-0352-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch [moved from target/linux/bcm27xx/patches-5.4/950-0357-staging-vchiq_arm-Set-up-dma-ranges-on-child-devices.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0353-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch [moved from target/linux/bcm27xx/patches-5.4/950-0358-staging-vchiq-Use-the-old-dma-controller-for-OF-conf.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0354-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch [moved from target/linux/bcm27xx/patches-5.4/950-0359-dwc_otg-checking-the-urb-transfer_buffer-too-early-3.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0355-overlays-Make-mcp342x-run-time-compatible.patch [moved from target/linux/bcm27xx/patches-5.4/950-0360-overlays-Make-mcp342x-run-time-compatible.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0356-rpi-cirrus-wm5102-overlay-use-reset-gpios-instead-of.patch [moved from target/linux/bcm27xx/patches-5.4/950-0361-rpi-cirrus-wm5102-overlay-use-reset-gpios-instead-of.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0357-sound-soc-only-first-codec-is-master-in-multicodec-s.patch [moved from target/linux/bcm27xx/patches-5.4/950-0362-sound-soc-only-first-codec-is-master-in-multicodec-s.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0358-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0363-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0359-overlays-dht11-Allow-multiple-instantiation.patch [moved from target/linux/bcm27xx/patches-5.4/950-0364-overlays-dht11-Allow-multiple-instantiation.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0360-overlays-i2c-rtc-Add-pcf85363-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0365-overlays-i2c-rtc-Add-pcf85363-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0361-pinctrl-bcm2835-Remove-gpiochip-on-error.patch [moved from target/linux/bcm27xx/patches-5.4/950-0366-pinctrl-bcm2835-Remove-gpiochip-on-error.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0362-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch [moved from target/linux/bcm27xx/patches-5.4/950-0367-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0363-Pisound-MIDI-communication-fixes-for-scaled-down-CPU.patch [moved from target/linux/bcm27xx/patches-5.4/950-0368-Pisound-MIDI-communication-fixes-for-scaled-down-CPU.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0364-ARM-dts-bcm283x-Remove-simple-bus-from-fixed-clocks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0369-ARM-dts-bcm283x-Remove-simple-bus-from-fixed-clocks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0365-ARM-dts-bcm283x-Move-system-timer-back-to-bcm283x.dt.patch [moved from target/linux/bcm27xx/patches-5.4/950-0370-ARM-dts-bcm283x-Move-system-timer-back-to-bcm283x.dt.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0366-ARM-dts-bcm283x-Move-pixelvalve-to-bcm2835-common.dt.patch [moved from target/linux/bcm27xx/patches-5.4/950-0371-ARM-dts-bcm283x-Move-pixelvalve-to-bcm2835-common.dt.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0367-ARM-dts-bcm2838-rpi-4-b-Fix-memory-node.patch [moved from target/linux/bcm27xx/patches-5.4/950-0372-ARM-dts-bcm2838-rpi-4-b-Fix-memory-node.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0368-ARM-dts-bcm2838-rpi-4-b-Backport-BT-part-from-upstre.patch [moved from target/linux/bcm27xx/patches-5.4/950-0373-ARM-dts-bcm2838-rpi-4-b-Backport-BT-part-from-upstre.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0369-ARM-dts-bcm2838-Backport-node-names-from-upstream.patch [moved from target/linux/bcm27xx/patches-5.4/950-0374-ARM-dts-bcm2838-Backport-node-names-from-upstream.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0370-ARM-dts-bcm283x-Move-intc-label-to-bcm2835-common.dt.patch [moved from target/linux/bcm27xx/patches-5.4/950-0375-ARM-dts-bcm283x-Move-intc-label-to-bcm2835-common.dt.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0371-ARM-dts-bcm2838-Remove-always-on-from-armv7-timer.patch [moved from target/linux/bcm27xx/patches-5.4/950-0376-ARM-dts-bcm2838-Remove-always-on-from-armv7-timer.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0372-net-bcmgenet-Add-RGMII_RXID-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0377-net-bcmgenet-Add-RGMII_RXID-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0373-ARM-dts-bcm2838-Backport-genet-from-upstream.patch [moved from target/linux/bcm27xx/patches-5.4/950-0378-ARM-dts-bcm2838-Backport-genet-from-upstream.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0374-ARM-bcm-Backport-BCM2711-support-from-upstream.patch [moved from target/linux/bcm27xx/patches-5.4/950-0379-ARM-bcm-Backport-BCM2711-support-from-upstream.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0375-hwrng-iproc-rng200-Add-support-for-BCM2711.patch [moved from target/linux/bcm27xx/patches-5.4/950-0380-hwrng-iproc-rng200-Add-support-for-BCM2711.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0376-ARM-dts-bcm2838-Add-upstream-RNG-compatible.patch [moved from target/linux/bcm27xx/patches-5.4/950-0381-ARM-dts-bcm2838-Add-upstream-RNG-compatible.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0377-driver-char-rpivid-Destroy-the-legacy-device-on-remo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0382-driver-char-rpivid-Destroy-the-legacy-device-on-remo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0378-driver-char-rpivid-Clean-up-error-handling-use-of-ER.patch [moved from target/linux/bcm27xx/patches-5.4/950-0383-driver-char-rpivid-Clean-up-error-handling-use-of-ER.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0379-driver-char-rpivid-Add-error-handling-to-the-legacy-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0384-driver-char-rpivid-Add-error-handling-to-the-legacy-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0380-driver-char-rpivid-Fix-coding-style-whitespace-issue.patch [moved from target/linux/bcm27xx/patches-5.4/950-0385-driver-char-rpivid-Fix-coding-style-whitespace-issue.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0381-driver-char-rpimem-Add-SPDX-licence-header.patch [moved from target/linux/bcm27xx/patches-5.4/950-0386-driver-char-rpimem-Add-SPDX-licence-header.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0382-driver-char-rpivid-Fix-access-to-freed-memory.patch [moved from target/linux/bcm27xx/patches-5.4/950-0387-driver-char-rpivid-Fix-access-to-freed-memory.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0383-add-BME680-to-i2c-sensor-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0388-add-BME680-to-i2c-sensor-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0384-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch [moved from target/linux/bcm27xx/patches-5.4/950-0389-dwc_otg-constrain-endpoint-max-packet-and-transfer-s.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0385-dwc_otg-fiq_fsm-pause-when-cancelling-split-transact.patch [moved from target/linux/bcm27xx/patches-5.4/950-0390-dwc_otg-fiq_fsm-pause-when-cancelling-split-transact.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0386-dwc_otg-fiq_fsm-add-a-barrier-on-entry-into-FIQ-hand.patch [moved from target/linux/bcm27xx/patches-5.4/950-0391-dwc_otg-fiq_fsm-add-a-barrier-on-entry-into-FIQ-hand.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0387-Add-universal-device-tree-overlay-for-SPI-devices.patch [moved from target/linux/bcm27xx/patches-5.4/950-0392-Add-universal-device-tree-overlay-for-SPI-devices.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0388-sound-Add-the-HiFiBerry-DAC-HD-version.patch [moved from target/linux/bcm27xx/patches-5.4/950-0393-sound-Add-the-HiFiBerry-DAC-HD-version.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0389-Initialise-rpi-firmware-before-clk-bcm2835.patch [moved from target/linux/bcm27xx/patches-5.4/950-0394-Initialise-rpi-firmware-before-clk-bcm2835.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0390-Fix-master-mode-settings-of-HiFiBerry-DAC-ADC-PRO-ca.patch [moved from target/linux/bcm27xx/patches-5.4/950-0395-Fix-master-mode-settings-of-HiFiBerry-DAC-ADC-PRO-ca.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0391-overlays-Use-preferred-compatible-strings.patch [moved from target/linux/bcm27xx/patches-5.4/950-0396-overlays-Use-preferred-compatible-strings.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0392-tty-amba-pl011-Add-un-throttle-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0397-tty-amba-pl011-Add-un-throttle-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0393-Fix-i2c-pwm-pca9685a-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0398-Fix-i2c-pwm-pca9685a-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0394-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-PRO-sound-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0399-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-PRO-sound-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0395-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-sound-card.patch [moved from target/linux/bcm27xx/patches-5.4/950-0400-adds-LED-OFF-feature-to-HiFiBerry-DAC-ADC-sound-card.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0396-adds-LED-OFF-feature-to-HiFiBerry-DAC-DAC-PRO-sound-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0401-adds-LED-OFF-feature-to-HiFiBerry-DAC-DAC-PRO-sound-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0397-pisound-Added-reading-Pisound-board-hardware-revisio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0402-pisound-Added-reading-Pisound-board-hardware-revisio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0398-mmc-sdhci-iproc-Fix-vmmc-regulators-on-iProc.patch [moved from target/linux/bcm27xx/patches-5.4/950-0403-mmc-sdhci-iproc-Fix-vmmc-regulators-on-iProc.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0399-ARM-dts-Declare-RPi-4B-SD-card-power-regulator.patch [moved from target/linux/bcm27xx/patches-5.4/950-0404-ARM-dts-Declare-RPi-4B-SD-card-power-regulator.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0400-bcm2838.dtsi-Use-BCM2711-PCIe-compatible-string.patch [moved from target/linux/bcm27xx/patches-5.4/950-0405-bcm2838.dtsi-Use-BCM2711-PCIe-compatible-string.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0401-ARM-dts-Remove-bcm2838-rpi-4-b.dts.patch [moved from target/linux/bcm27xx/patches-5.4/950-0406-ARM-dts-Remove-bcm2838-rpi-4-b.dts.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0402-tty-amba-pl011-Avoid-rare-write-when-full-error.patch [moved from target/linux/bcm27xx/patches-5.4/950-0407-tty-amba-pl011-Avoid-rare-write-when-full-error.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0403-usb-xhci-Raspberry-Pi-FW-loader-for-VIA-VL805.patch [moved from target/linux/bcm27xx/patches-5.4/950-0408-usb-xhci-Raspberry-Pi-FW-loader-for-VIA-VL805.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0404-overlays-Correct-the-eth_led-colour-assignments.patch [moved from target/linux/bcm27xx/patches-5.4/950-0409-overlays-Correct-the-eth_led-colour-assignments.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0405-ARM-dts-Add-sd_poll_once-dtparam-to-bcm283x-2711.patch [moved from target/linux/bcm27xx/patches-5.4/950-0410-ARM-dts-Add-sd_poll_once-dtparam-to-bcm283x-2711.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0406-overlays-Add-ssd1306-spi-ssh1106-spi-ssd-1351-spi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0411-overlays-Add-ssd1306-spi-ssh1106-spi-ssd-1351-spi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0407-overlays-dwc2-Increase-RX-FIFO-size.patch [moved from target/linux/bcm27xx/patches-5.4/950-0412-overlays-dwc2-Increase-RX-FIFO-size.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0408-overlays-Fix-mcp23017-s-addr-parameter.patch [moved from target/linux/bcm27xx/patches-5.4/950-0413-overlays-Fix-mcp23017-s-addr-parameter.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0409-SQUASH-Fix-spi-driver-compiler-warnings.patch [moved from target/linux/bcm27xx/patches-5.4/950-0414-SQUASH-Fix-spi-driver-compiler-warnings.patch with 90% similarity]
target/linux/bcm27xx/patches-5.4/950-0410-overlays-add-hdmi-backlight-hwhack-gpio-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0415-overlays-add-hdmi-backlight-hwhack-gpio-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0411-ARM-dts-Revert-all-changes-to-upstream-dts-files.patch [moved from target/linux/bcm27xx/patches-5.4/950-0416-ARM-dts-Revert-all-changes-to-upstream-dts-files.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0412-ARM-dts-Clean-out-downstream-BCM2711-2838-files.patch [moved from target/linux/bcm27xx/patches-5.4/950-0417-ARM-dts-Clean-out-downstream-BCM2711-2838-files.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0413-ARM-dts-Add-minimal-Raspberry-Pi-4-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0418-ARM-dts-Add-minimal-Raspberry-Pi-4-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0414-ARM-dts-bcm2711-force-CMA-into-first-GB-of-memory.patch [moved from target/linux/bcm27xx/patches-5.4/950-0419-ARM-dts-bcm2711-force-CMA-into-first-GB-of-memory.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0415-ARM-dts-bcm2711-rpi-4-Enable-GENET-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0420-ARM-dts-bcm2711-rpi-4-Enable-GENET-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0416-ARM-dts-bcm2711-fix-soc-s-node-dma-ranges.patch [moved from target/linux/bcm27xx/patches-5.4/950-0421-ARM-dts-bcm2711-fix-soc-s-node-dma-ranges.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0417-ARM-dts-Rebuild-downstream-DTS-files.patch [moved from target/linux/bcm27xx/patches-5.4/950-0422-ARM-dts-Rebuild-downstream-DTS-files.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0418-staging-vchiq_arm-Fix-bcm2711-compatible-string.patch [moved from target/linux/bcm27xx/patches-5.4/950-0423-staging-vchiq_arm-Fix-bcm2711-compatible-string.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0419-hwrng-iproc-rng200-Correct-SoC-name.patch [moved from target/linux/bcm27xx/patches-5.4/950-0424-hwrng-iproc-rng200-Correct-SoC-name.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0420-ARM-dts-Correct-SoC-name.patch [moved from target/linux/bcm27xx/patches-5.4/950-0425-ARM-dts-Correct-SoC-name.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0421-ARM-dts-Remove-CMA-allocation-from-Pi-4-dts.patch [moved from target/linux/bcm27xx/patches-5.4/950-0426-ARM-dts-Remove-CMA-allocation-from-Pi-4-dts.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0422-staging-vchiq_arm-Give-vchiq-children-DT-nodes.patch [moved from target/linux/bcm27xx/patches-5.4/950-0427-staging-vchiq_arm-Give-vchiq-children-DT-nodes.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0423-ARM-dts-Move-audio-node-under-the-vchiq-parent.patch [moved from target/linux/bcm27xx/patches-5.4/950-0429-ARM-dts-Move-audio-node-under-the-vchiq-parent.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0424-ARM-dts-overlays-Create-custom-clocks-in.patch [moved from target/linux/bcm27xx/patches-5.4/950-0430-ARM-dts-overlays-Create-custom-clocks-in.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0425-staging-vc04_services-Fix-vcsm-overflow-bug-when-cou.patch [moved from target/linux/bcm27xx/patches-5.4/950-0431-staging-vc04_services-Fix-vcsm-overflow-bug-when-cou.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0426-overlays-Add-timeout_ms-parameter-to-gpio-poweroff.patch [moved from target/linux/bcm27xx/patches-5.4/950-0432-overlays-Add-timeout_ms-parameter-to-gpio-poweroff.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0427-of-overlay-Correct-symbol-path-fixups.patch [moved from target/linux/bcm27xx/patches-5.4/950-0433-of-overlay-Correct-symbol-path-fixups.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0428-overlays-sc16ic750-i2c-Fix-xtal-parameter.patch [moved from target/linux/bcm27xx/patches-5.4/950-0434-overlays-sc16ic750-i2c-Fix-xtal-parameter.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0429-of-address-Introduce-of_get_next_dma_parent-helper.patch [moved from target/linux/bcm27xx/patches-5.4/950-0435-of-address-Introduce-of_get_next_dma_parent-helper.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0430-of-address-Follow-DMA-parent-for-dma-coherent.patch [moved from target/linux/bcm27xx/patches-5.4/950-0436-of-address-Follow-DMA-parent-for-dma-coherent.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0431-of-Factor-out-addr-size-cells-parsing.patch [moved from target/linux/bcm27xx/patches-5.4/950-0437-of-Factor-out-addr-size-cells-parsing.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0432-of-address-Translate-dma-ranges-for-parent-nodes-mis.patch [moved from target/linux/bcm27xx/patches-5.4/950-0438-of-address-Translate-dma-ranges-for-parent-nodes-mis.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0433-of-Make-of_dma_get_range-work-on-bus-nodes.patch [moved from target/linux/bcm27xx/patches-5.4/950-0439-of-Make-of_dma_get_range-work-on-bus-nodes.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0434-arm64-mm-use-arm64_dma_phys_limit-instead-of-calling.patch [moved from target/linux/bcm27xx/patches-5.4/950-0440-arm64-mm-use-arm64_dma_phys_limit-instead-of-calling.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0435-arm64-rename-variables-used-to-calculate-ZONE_DMA32-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0441-arm64-rename-variables-used-to-calculate-ZONE_DMA32-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0436-arm64-use-both-ZONE_DMA-and-ZONE_DMA32.patch [moved from target/linux/bcm27xx/patches-5.4/950-0442-arm64-use-both-ZONE_DMA-and-ZONE_DMA32.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0437-mm-refresh-ZONE_DMA-and-ZONE_DMA32-comments-in-enum-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0443-mm-refresh-ZONE_DMA-and-ZONE_DMA32-comments-in-enum-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0438-resource-Add-a-resource_list_first_type-helper.patch [moved from target/linux/bcm27xx/patches-5.4/950-0444-resource-Add-a-resource_list_first_type-helper.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0439-dma-direct-turn-ARCH_ZONE_DMA_BITS-into-a-variable.patch [moved from target/linux/bcm27xx/patches-5.4/950-0445-dma-direct-turn-ARCH_ZONE_DMA_BITS-into-a-variable.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0440-x86-PCI-sta2x11-use-default-DMA-address-translation.patch [moved from target/linux/bcm27xx/patches-5.4/950-0446-x86-PCI-sta2x11-use-default-DMA-address-translation.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0441-PCI-of-Add-inbound-resource-parsing-to-helpers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0447-PCI-of-Add-inbound-resource-parsing-to-helpers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0442-dma-direct-unify-the-dma_capable-definitions.patch [moved from target/linux/bcm27xx/patches-5.4/950-0448-dma-direct-unify-the-dma_capable-definitions.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0443-dma-direct-avoid-a-forward-declaration-for-phys_to_d.patch [moved from target/linux/bcm27xx/patches-5.4/950-0449-dma-direct-avoid-a-forward-declaration-for-phys_to_d.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0444-dma-direct-exclude-dma_direct_map_resource-from-the-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0450-dma-direct-exclude-dma_direct_map_resource-from-the-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0445-dma-mapping-treat-dev-bus_dma_mask-as-a-DMA-limit.patch [moved from target/linux/bcm27xx/patches-5.4/950-0451-dma-mapping-treat-dev-bus_dma_mask-as-a-DMA-limit.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0446-ARM-dts-bcm2711-Enable-PCIe-controller.patch [moved from target/linux/bcm27xx/patches-5.4/950-0452-ARM-dts-bcm2711-Enable-PCIe-controller.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0447-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch [moved from target/linux/bcm27xx/patches-5.4/950-0453-PCI-brcmstb-Add-Broadcom-STB-PCIe-host-controller-dr.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0448-PCI-brcmstb-Add-MSI-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0454-PCI-brcmstb-Add-MSI-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0449-PCI-brcmstb-Fix-build-on-32bit-ARM-platforms-with-ol.patch [moved from target/linux/bcm27xx/patches-5.4/950-0455-PCI-brcmstb-Fix-build-on-32bit-ARM-platforms-with-ol.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0450-bcm2711-rpi.dtsi-Use-upstream-pcie-node.patch [moved from target/linux/bcm27xx/patches-5.4/950-0456-bcm2711-rpi.dtsi-Use-upstream-pcie-node.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0451-media-dt-bindings-media-i2c-Add-IMX219-CMOS-sensor-b.patch [moved from target/linux/bcm27xx/patches-5.4/950-0457-media-dt-bindings-media-i2c-Add-IMX219-CMOS-sensor-b.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0452-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch [moved from target/linux/bcm27xx/patches-5.4/950-0458-media-i2c-Add-driver-for-Sony-IMX219-sensor.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0453-overlays-imx219-Correct-link-frequency-to-match-the-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0459-overlays-imx219-Correct-link-frequency-to-match-the-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0454-Kbuild-Allow-.dtbo-overlays-to-be-built-adjust.patch [moved from target/linux/bcm27xx/patches-5.4/950-0460-Kbuild-Allow-.dtbo-overlays-to-be-built-adjust.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0455-media-ov5647-Fix-return-codes-from-ov5647_write-ov56.patch [moved from target/linux/bcm27xx/patches-5.4/950-0461-media-ov5647-Fix-return-codes-from-ov5647_write-ov56.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0456-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch [moved from target/linux/bcm27xx/patches-5.4/950-0462-media-ov5647-Add-basic-support-for-multiple-sensor-m.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0457-media-ov5647-Add-V4L2-controls-for-analogue-gain-exp.patch [moved from target/linux/bcm27xx/patches-5.4/950-0463-media-ov5647-Add-V4L2-controls-for-analogue-gain-exp.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0458-media-ov5647-Add-extra-10-bit-sensor-modes.patch [moved from target/linux/bcm27xx/patches-5.4/950-0464-media-ov5647-Add-extra-10-bit-sensor-modes.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0459-media-ov5647-change-defaults-to-better-match-raw-cam.patch [moved from target/linux/bcm27xx/patches-5.4/950-0465-media-ov5647-change-defaults-to-better-match-raw-cam.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0460-drm-vc4-fkms-Change-crtc_state-structure-name-to-avo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0466-drm-vc4-fkms-Change-crtc_state-structure-name-to-avo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0461-drm-fourcc-Add-packed-10bit-YUV-4-2-0-format.patch [moved from target/linux/bcm27xx/patches-5.4/950-0467-drm-fourcc-Add-packed-10bit-YUV-4-2-0-format.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0462-drm-vc4-Add-DRM_FORMAT_P030-support-to-firmware-kms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0468-drm-vc4-Add-DRM_FORMAT_P030-support-to-firmware-kms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0463-gpio-ir-overlay-add-parameter-to-configure-signal-po.patch [moved from target/linux/bcm27xx/patches-5.4/950-0469-gpio-ir-overlay-add-parameter-to-configure-signal-po.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0464-Add-support-for-merus-amp-soundcard-and-ma120x0p-cod.patch [moved from target/linux/bcm27xx/patches-5.4/950-0470-Add-support-for-merus-amp-soundcard-and-ma120x0p-cod.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0465-ARM-dts-bcm2711-Add-32-bit-PMU-compatibility.patch [moved from target/linux/bcm27xx/patches-5.4/950-0471-ARM-dts-bcm2711-Add-32-bit-PMU-compatibility.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0466-ARM-dts-bcm271x-Use-a53-pmu-drop-RPI364.patch [moved from target/linux/bcm27xx/patches-5.4/950-0472-ARM-dts-bcm271x-Use-a53-pmu-drop-RPI364.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0467-net-bcmgenet-Clear-ID_MODE_DIS-in-EXT_RGMII_OOB_CTRL.patch [moved from target/linux/bcm27xx/patches-5.4/950-0473-net-bcmgenet-Clear-ID_MODE_DIS-in-EXT_RGMII_OOB_CTRL.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0468-drm-modes-parse_cmdline-Fix-possible-reference-past-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0474-drm-modes-parse_cmdline-Fix-possible-reference-past-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0469-drm-modes-parse_cmdline-Make-various-char-pointers-c.patch [moved from target/linux/bcm27xx/patches-5.4/950-0475-drm-modes-parse_cmdline-Make-various-char-pointers-c.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0470-drm-modes-parse_cmdline-Stop-parsing-extras-after-bp.patch [moved from target/linux/bcm27xx/patches-5.4/950-0476-drm-modes-parse_cmdline-Stop-parsing-extras-after-bp.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0471-drm-modes-parse_cmdline-Accept-extras-directly-after.patch [moved from target/linux/bcm27xx/patches-5.4/950-0477-drm-modes-parse_cmdline-Accept-extras-directly-after.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0472-drm-modes-parse_cmdline-Rework-drm_mode_parse_cmdlin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0478-drm-modes-parse_cmdline-Rework-drm_mode_parse_cmdlin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0473-drm-modes-parse_cmdline-Add-freestanding-argument-to.patch [moved from target/linux/bcm27xx/patches-5.4/950-0479-drm-modes-parse_cmdline-Add-freestanding-argument-to.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0474-drm-modes-parse_cmdline-Set-bpp-refresh_specified-af.patch [moved from target/linux/bcm27xx/patches-5.4/950-0480-drm-modes-parse_cmdline-Set-bpp-refresh_specified-af.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0475-drm-modes-parse_cmdline-Allow-specifying-stand-alone.patch [moved from target/linux/bcm27xx/patches-5.4/950-0481-drm-modes-parse_cmdline-Allow-specifying-stand-alone.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0476-drm-modes-parse_cmdline-Add-support-for-specifying-p.patch [moved from target/linux/bcm27xx/patches-5.4/950-0482-drm-modes-parse_cmdline-Add-support-for-specifying-p.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0477-drm-modes-parse_cmdline-Remove-some-unnecessary-code.patch [moved from target/linux/bcm27xx/patches-5.4/950-0483-drm-modes-parse_cmdline-Remove-some-unnecessary-code.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0478-drm-modes-parse_cmdline-Explicitly-memset-the-passed.patch [moved from target/linux/bcm27xx/patches-5.4/950-0484-drm-modes-parse_cmdline-Explicitly-memset-the-passed.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0479-drm-v3d-Replace-wait_for-macros-to-remove-use-of-msl.patch [moved from target/linux/bcm27xx/patches-5.4/950-0485-drm-v3d-Replace-wait_for-macros-to-remove-use-of-msl.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0480-Reduce-noise-from-rpi-poe-hat-fan.patch [moved from target/linux/bcm27xx/patches-5.4/950-0486-Reduce-noise-from-rpi-poe-hat-fan.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0481-add-Sensirion-SPS30-to-i2c-sensor-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0487-add-Sensirion-SPS30-to-i2c-sensor-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0482-media-add-V4L2_CTRL_TYPE_AREA-control-type.patch [moved from target/linux/bcm27xx/patches-5.4/950-0488-media-add-V4L2_CTRL_TYPE_AREA-control-type.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0483-media-add-V4L2_CID_UNIT_CELL_SIZE-control.patch [moved from target/linux/bcm27xx/patches-5.4/950-0489-media-add-V4L2_CID_UNIT_CELL_SIZE-control.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0484-media-v4l2-common-add-pixel-encoding-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0490-media-v4l2-common-add-pixel-encoding-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0485-media-v4l2-common-add-RGB565-and-RGB55-to-v4l2_forma.patch [moved from target/linux/bcm27xx/patches-5.4/950-0491-media-v4l2-common-add-RGB565-and-RGB55-to-v4l2_forma.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0486-media-vb2-add-V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF.patch [moved from target/linux/bcm27xx/patches-5.4/950-0492-media-vb2-add-V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0487-media-v4l2-mem2mem-support-held-capture-buffers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0493-media-v4l2-mem2mem-support-held-capture-buffers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0488-media-videodev2.h-add-V4L2_DEC_CMD_FLUSH.patch [moved from target/linux/bcm27xx/patches-5.4/950-0494-media-videodev2.h-add-V4L2_DEC_CMD_FLUSH.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0489-media-v4l2-mem2mem-add-stateless_-try_-decoder_cmd-i.patch [moved from target/linux/bcm27xx/patches-5.4/950-0495-media-v4l2-mem2mem-add-stateless_-try_-decoder_cmd-i.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0490-media-v4l2-mem2mem-add-new_frame-detection.patch [moved from target/linux/bcm27xx/patches-5.4/950-0496-media-v4l2-mem2mem-add-new_frame-detection.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0491-media-Documentation-media-Document-V4L2_CTRL_TYPE_AR.patch [moved from target/linux/bcm27xx/patches-5.4/950-0497-media-Documentation-media-Document-V4L2_CTRL_TYPE_AR.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0492-media-v4l-Add-definitions-for-HEVC-stateless-decodin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0498-media-v4l-Add-definitions-for-HEVC-stateless-decodin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0493-media-v4l2-mem2mem-Fix-hold-buf-flag-checks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0499-media-v4l2-mem2mem-Fix-hold-buf-flag-checks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0494-media-pixfmt-Document-the-HEVC-slice-pixel-format.patch [moved from target/linux/bcm27xx/patches-5.4/950-0500-media-pixfmt-Document-the-HEVC-slice-pixel-format.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0495-media-uapi-hevc-Add-scaling-matrix-control.patch [moved from target/linux/bcm27xx/patches-5.4/950-0501-media-uapi-hevc-Add-scaling-matrix-control.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0496-media-uapi-hevc-Add-segment-address-field.patch [moved from target/linux/bcm27xx/patches-5.4/950-0502-media-uapi-hevc-Add-segment-address-field.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0497-media-hevc_ctrls-Add-slice-param-dependent-slice-seg.patch [moved from target/linux/bcm27xx/patches-5.4/950-0503-media-hevc_ctrls-Add-slice-param-dependent-slice-seg.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0498-media-uapi-Add-hevc-ctrls-for-WPP-decoding.patch [moved from target/linux/bcm27xx/patches-5.4/950-0504-media-uapi-Add-hevc-ctrls-for-WPP-decoding.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0499-media-videodev2.h-Add-a-format-for-column-YUV4-2-0-m.patch [moved from target/linux/bcm27xx/patches-5.4/950-0505-media-videodev2.h-Add-a-format-for-column-YUV4-2-0-m.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0500-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0506-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0501-media-dt-bindings-media-Add-binding-for-the-Raspberr.patch [moved from target/linux/bcm27xx/patches-5.4/950-0507-media-dt-bindings-media-Add-binding-for-the-Raspberr.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0502-staging-media-Add-Raspberry-Pi-V4L2-H265-decoder.patch [moved from target/linux/bcm27xx/patches-5.4/950-0508-staging-media-Add-Raspberry-Pi-V4L2-H265-decoder.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0503-dtoverlays-Add-overlay-to-enable-the-HEVC-V4L2-drive.patch [moved from target/linux/bcm27xx/patches-5.4/950-0509-dtoverlays-Add-overlay-to-enable-the-HEVC-V4L2-drive.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0504-mmc-sdhci-Silence-MMC-warnings.patch [moved from target/linux/bcm27xx/patches-5.4/950-0510-mmc-sdhci-Silence-MMC-warnings.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0505-dt-bindings-i2c-brcmstb-Convert-the-BRCMSTB-binding-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0511-dt-bindings-i2c-brcmstb-Convert-the-BRCMSTB-binding-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0506-dt-bindings-i2c-brcmstb-Add-BCM2711-BSC-AUTO-I2C-bin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0512-dt-bindings-i2c-brcmstb-Add-BCM2711-BSC-AUTO-I2C-bin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0507-i2c-brcmstb-Support-BCM2711-HDMI-BSC-controllers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0513-i2c-brcmstb-Support-BCM2711-HDMI-BSC-controllers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0508-i2c-brcmstb-Allow-to-compile-it-on-BCM2835.patch [moved from target/linux/bcm27xx/patches-5.4/950-0514-i2c-brcmstb-Allow-to-compile-it-on-BCM2835.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0509-dt-bindings-clock-Add-a-binding-for-the-RPi-Firmware.patch [moved from target/linux/bcm27xx/patches-5.4/950-0515-dt-bindings-clock-Add-a-binding-for-the-RPi-Firmware.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0510-clk-bcm-rpi-Allow-the-driver-to-be-probed-by-DT.patch [moved from target/linux/bcm27xx/patches-5.4/950-0516-clk-bcm-rpi-Allow-the-driver-to-be-probed-by-DT.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0511-clk-bcm-rpi-Statically-init-clk_init_data.patch [moved from target/linux/bcm27xx/patches-5.4/950-0517-clk-bcm-rpi-Statically-init-clk_init_data.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0512-clk-bcm-rpi-Use-clk_hw_register-for-pllb_arm.patch [moved from target/linux/bcm27xx/patches-5.4/950-0518-clk-bcm-rpi-Use-clk_hw_register-for-pllb_arm.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0513-clk-bcm-rpi-Remove-global-pllb_arm-clock-pointer.patch [moved from target/linux/bcm27xx/patches-5.4/950-0519-clk-bcm-rpi-Remove-global-pllb_arm-clock-pointer.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0514-clk-bcm-rpi-Make-sure-pllb_arm-is-removed.patch [moved from target/linux/bcm27xx/patches-5.4/950-0520-clk-bcm-rpi-Make-sure-pllb_arm-is-removed.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0515-clk-bcm-rpi-Remove-pllb_arm_lookup-global-pointer.patch [moved from target/linux/bcm27xx/patches-5.4/950-0521-clk-bcm-rpi-Remove-pllb_arm_lookup-global-pointer.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0516-clk-bcm-rpi-Switch-to-clk_hw_register_clkdev.patch [moved from target/linux/bcm27xx/patches-5.4/950-0522-clk-bcm-rpi-Switch-to-clk_hw_register_clkdev.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0517-clk-bcm-rpi-Make-sure-the-clkdev-lookup-is-removed.patch [moved from target/linux/bcm27xx/patches-5.4/950-0523-clk-bcm-rpi-Make-sure-the-clkdev-lookup-is-removed.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0518-clk-bcm-rpi-Create-a-data-structure-for-the-clocks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0524-clk-bcm-rpi-Create-a-data-structure-for-the-clocks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0519-clk-bcm-rpi-Add-clock-id-to-data.patch [moved from target/linux/bcm27xx/patches-5.4/950-0525-clk-bcm-rpi-Add-clock-id-to-data.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0520-clk-bcm-rpi-Pass-the-clocks-data-to-the-firmware-fun.patch [moved from target/linux/bcm27xx/patches-5.4/950-0526-clk-bcm-rpi-Pass-the-clocks-data-to-the-firmware-fun.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0521-clk-bcm-rpi-Rename-is_prepared-function.patch [moved from target/linux/bcm27xx/patches-5.4/950-0527-clk-bcm-rpi-Rename-is_prepared-function.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0522-clk-bcm-rpi-Split-pllb-clock-hooks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0528-clk-bcm-rpi-Split-pllb-clock-hooks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0523-clk-bcm-rpi-Make-the-PLLB-registration-function-retu.patch [moved from target/linux/bcm27xx/patches-5.4/950-0529-clk-bcm-rpi-Make-the-PLLB-registration-function-retu.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0524-clk-bcm-rpi-Add-DT-provider-for-the-clocks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0530-clk-bcm-rpi-Add-DT-provider-for-the-clocks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0525-clk-bcm-rpi-Discover-the-firmware-clocks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0531-clk-bcm-rpi-Discover-the-firmware-clocks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0526-ARM-dts-bcm2711-Add-firmware-clocks-node.patch [moved from target/linux/bcm27xx/patches-5.4/950-0532-ARM-dts-bcm2711-Add-firmware-clocks-node.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0527-reset-Move-reset-simple-header-out-of-drivers-reset.patch [moved from target/linux/bcm27xx/patches-5.4/950-0533-reset-Move-reset-simple-header-out-of-drivers-reset.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0528-reset-simple-Add-reset-callback.patch [moved from target/linux/bcm27xx/patches-5.4/950-0534-reset-simple-Add-reset-callback.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0529-dt-bindings-clock-Add-BCM2711-DVP-binding.patch [moved from target/linux/bcm27xx/patches-5.4/950-0535-dt-bindings-clock-Add-BCM2711-DVP-binding.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0530-clk-bcm-Add-BCM2711-DVP-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0536-clk-bcm-Add-BCM2711-DVP-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0531-ARM-dts-bcm2711-Add-HDMI-DVP.patch [moved from target/linux/bcm27xx/patches-5.4/950-0537-ARM-dts-bcm2711-Add-HDMI-DVP.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0532-dt-bindings-display-Convert-VC4-bindings-to-schemas.patch [moved from target/linux/bcm27xx/patches-5.4/950-0538-dt-bindings-display-Convert-VC4-bindings-to-schemas.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0533-dt-bindings-display-vc4-dpi-Add-missing-clock-names-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0539-dt-bindings-display-vc4-dpi-Add-missing-clock-names-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0534-dt-bindings-display-vc4-dsi-Add-missing-clock-proper.patch [moved from target/linux/bcm27xx/patches-5.4/950-0540-dt-bindings-display-vc4-dsi-Add-missing-clock-proper.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0535-dt-bindings-display-vc4-hdmi-Add-missing-clock-names.patch [moved from target/linux/bcm27xx/patches-5.4/950-0541-dt-bindings-display-vc4-hdmi-Add-missing-clock-names.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0536-dt-bindings-display-vc4-Document-BCM2711-VC5.patch [moved from target/linux/bcm27xx/patches-5.4/950-0542-dt-bindings-display-vc4-Document-BCM2711-VC5.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0537-drm-vc4-drv-Add-include-guards.patch [moved from target/linux/bcm27xx/patches-5.4/950-0543-drm-vc4-drv-Add-include-guards.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0538-drm-vc4-drv-Support-BCM2711.patch [moved from target/linux/bcm27xx/patches-5.4/950-0544-drm-vc4-drv-Support-BCM2711.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0539-drm-vc4-drv-Add-support-for-the-BCM2711-HVS5.patch [moved from target/linux/bcm27xx/patches-5.4/950-0545-drm-vc4-drv-Add-support-for-the-BCM2711-HVS5.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0540-drm-vc4-plane-Improve-LBM-usage.patch [moved from target/linux/bcm27xx/patches-5.4/950-0546-drm-vc4-plane-Improve-LBM-usage.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0541-drm-vc4-plane-Move-planes-creation-to-its-own-functi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0547-drm-vc4-plane-Move-planes-creation-to-its-own-functi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0542-drm-vc4-plane-Move-additional-planes-creation-to-dri.patch [moved from target/linux/bcm27xx/patches-5.4/950-0548-drm-vc4-plane-Move-additional-planes-creation-to-dri.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0543-drm-vc4-plane-Register-all-the-planes-at-once.patch [moved from target/linux/bcm27xx/patches-5.4/950-0549-drm-vc4-plane-Register-all-the-planes-at-once.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0544-drm-vc4-plane-Create-overlays-for-any-CRTC.patch [moved from target/linux/bcm27xx/patches-5.4/950-0550-drm-vc4-plane-Create-overlays-for-any-CRTC.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0545-drm-vc4-plane-Create-more-planes.patch [moved from target/linux/bcm27xx/patches-5.4/950-0551-drm-vc4-plane-Create-more-planes.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0546-drm-vc4-crtc-Rename-SoC-data-structures.patch [moved from target/linux/bcm27xx/patches-5.4/950-0552-drm-vc4-crtc-Rename-SoC-data-structures.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0547-drm-vc4-crtc-Move-crtc-state-to-common-header.patch [moved from target/linux/bcm27xx/patches-5.4/950-0553-drm-vc4-crtc-Move-crtc-state-to-common-header.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0548-drm-vc4-crtc-Deal-with-different-number-of-pixel-per.patch [moved from target/linux/bcm27xx/patches-5.4/950-0554-drm-vc4-crtc-Deal-with-different-number-of-pixel-per.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0549-drm-vc4-crtc-Use-a-shared-interrupt.patch [moved from target/linux/bcm27xx/patches-5.4/950-0555-drm-vc4-crtc-Use-a-shared-interrupt.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0550-drm-vc4-crtc-Turn-static-const-variable-into-a-defin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0556-drm-vc4-crtc-Turn-static-const-variable-into-a-defin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0551-drm-vc4-crtc-Move-the-cob-allocation-outside-of-bind.patch [moved from target/linux/bcm27xx/patches-5.4/950-0557-drm-vc4-crtc-Move-the-cob-allocation-outside-of-bind.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0552-drm-vc4-crtc-Rename-HVS-channel-to-output.patch [moved from target/linux/bcm27xx/patches-5.4/950-0558-drm-vc4-crtc-Rename-HVS-channel-to-output.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0553-drm-vc4-crtc-Use-local-chan-variable.patch [moved from target/linux/bcm27xx/patches-5.4/950-0559-drm-vc4-crtc-Use-local-chan-variable.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0554-drm-vc4-crtc-Enable-and-disable-the-PV-in-atomic_ena.patch [moved from target/linux/bcm27xx/patches-5.4/950-0560-drm-vc4-crtc-Enable-and-disable-the-PV-in-atomic_ena.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0555-drm-vc4-crtc-Assign-output-to-channel-automatically.patch [moved from target/linux/bcm27xx/patches-5.4/950-0561-drm-vc4-crtc-Assign-output-to-channel-automatically.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0556-drm-vc4-crtc-Add-FIFO-depth-to-vc4_crtc_data.patch [moved from target/linux/bcm27xx/patches-5.4/950-0562-drm-vc4-crtc-Add-FIFO-depth-to-vc4_crtc_data.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0557-drm-vc4-crtc-Add-function-to-compute-FIFO-level-bits.patch [moved from target/linux/bcm27xx/patches-5.4/950-0563-drm-vc4-crtc-Add-function-to-compute-FIFO-level-bits.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0558-drm-vc4-crtc-Rename-HDMI-encoder-type-to-HDMI0.patch [moved from target/linux/bcm27xx/patches-5.4/950-0564-drm-vc4-crtc-Rename-HDMI-encoder-type-to-HDMI0.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0559-drm-vc4-crtc-Add-HDMI1-encoder-type.patch [moved from target/linux/bcm27xx/patches-5.4/950-0565-drm-vc4-crtc-Add-HDMI1-encoder-type.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0560-drm-vc4-crtc-Remove-redundant-call-to-drm_crtc_enabl.patch [moved from target/linux/bcm27xx/patches-5.4/950-0566-drm-vc4-crtc-Remove-redundant-call-to-drm_crtc_enabl.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0561-drm-vc4-crtc-Disable-color-management-for-HVS5.patch [moved from target/linux/bcm27xx/patches-5.4/950-0567-drm-vc4-crtc-Disable-color-management-for-HVS5.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0562-dt-bindings-display-vc4-pv-Add-BCM2711-pixel-valves.patch [moved from target/linux/bcm27xx/patches-5.4/950-0568-dt-bindings-display-vc4-pv-Add-BCM2711-pixel-valves.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0563-drm-vc4-crtc-Add-BCM2711-pixelvalves.patch [moved from target/linux/bcm27xx/patches-5.4/950-0569-drm-vc4-crtc-Add-BCM2711-pixelvalves.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0564-drm-vc4-hdmi-Use-debugfs-private-field.patch [moved from target/linux/bcm27xx/patches-5.4/950-0570-drm-vc4-hdmi-Use-debugfs-private-field.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0565-drm-vc4-hdmi-Move-structure-to-header.patch [moved from target/linux/bcm27xx/patches-5.4/950-0571-drm-vc4-hdmi-Move-structure-to-header.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0566-drm-vc4-hdmi-rework-connectors-and-encoders.patch [moved from target/linux/bcm27xx/patches-5.4/950-0572-drm-vc4-hdmi-rework-connectors-and-encoders.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0567-drm-vc4-hdmi-Rename-hdmi-to-vc4_hdmi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0573-drm-vc4-hdmi-Rename-hdmi-to-vc4_hdmi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0568-drm-vc4-hdmi-Move-accessors-to-vc4_hdmi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0574-drm-vc4-hdmi-Move-accessors-to-vc4_hdmi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0569-drm-vc4-hdmi-Use-local-vc4_hdmi-directly.patch [moved from target/linux/bcm27xx/patches-5.4/950-0575-drm-vc4-hdmi-Use-local-vc4_hdmi-directly.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0570-drm-vc4-hdmi-Add-container_of-macros-for-encoders-an.patch [moved from target/linux/bcm27xx/patches-5.4/950-0576-drm-vc4-hdmi-Add-container_of-macros-for-encoders-an.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0571-drm-vc4-hdmi-Pass-vc4_hdmi-to-CEC-code.patch [moved from target/linux/bcm27xx/patches-5.4/950-0577-drm-vc4-hdmi-Pass-vc4_hdmi-to-CEC-code.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0572-drm-vc4-hdmi-Remove-vc4_dev-hdmi-pointer.patch [moved from target/linux/bcm27xx/patches-5.4/950-0578-drm-vc4-hdmi-Remove-vc4_dev-hdmi-pointer.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0573-drm-vc4-hdmi-Remove-vc4_hdmi_connector.patch [moved from target/linux/bcm27xx/patches-5.4/950-0579-drm-vc4-hdmi-Remove-vc4_hdmi_connector.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0574-drm-vc4-hdmi-Introduce-resource-init-and-variant.patch [moved from target/linux/bcm27xx/patches-5.4/950-0580-drm-vc4-hdmi-Introduce-resource-init-and-variant.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0575-drm-vc4-hdmi-Implement-a-register-layout-abstraction.patch [moved from target/linux/bcm27xx/patches-5.4/950-0581-drm-vc4-hdmi-Implement-a-register-layout-abstraction.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0576-drm-vc4-hdmi-Add-reset-callback.patch [moved from target/linux/bcm27xx/patches-5.4/950-0582-drm-vc4-hdmi-Add-reset-callback.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0577-drm-vc4-hdmi-Add-PHY-init-and-disable-function.patch [moved from target/linux/bcm27xx/patches-5.4/950-0583-drm-vc4-hdmi-Add-PHY-init-and-disable-function.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0578-drm-vc4-hdmi-Add-PHY-RNG-enable-disable-function.patch [moved from target/linux/bcm27xx/patches-5.4/950-0584-drm-vc4-hdmi-Add-PHY-RNG-enable-disable-function.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0579-drm-vc4-hdmi-Add-a-CSC-setup-callback.patch [moved from target/linux/bcm27xx/patches-5.4/950-0585-drm-vc4-hdmi-Add-a-CSC-setup-callback.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0580-drm-vc4-hdmi-Add-a-set_timings-callback.patch [moved from target/linux/bcm27xx/patches-5.4/950-0586-drm-vc4-hdmi-Add-a-set_timings-callback.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0581-drm-vc4-hdmi-Add-HDMI-ID.patch [moved from target/linux/bcm27xx/patches-5.4/950-0587-drm-vc4-hdmi-Add-HDMI-ID.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0582-drm-vc4-hdmi-Deal-with-multiple-debugfs-files.patch [moved from target/linux/bcm27xx/patches-5.4/950-0588-drm-vc4-hdmi-Deal-with-multiple-debugfs-files.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0583-drm-vc4-hdmi-Add-an-audio-support-flag.patch [moved from target/linux/bcm27xx/patches-5.4/950-0589-drm-vc4-hdmi-Add-an-audio-support-flag.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0584-drm-vc4-hdmi-Move-CEC-init-to-its-own-function.patch [moved from target/linux/bcm27xx/patches-5.4/950-0590-drm-vc4-hdmi-Move-CEC-init-to-its-own-function.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0585-drm-vc4-hdmi-Add-CEC-support-flag.patch [moved from target/linux/bcm27xx/patches-5.4/950-0591-drm-vc4-hdmi-Add-CEC-support-flag.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0586-drm-vc4-hdmi-Remove-unused-CEC_CLOCK_DIV-define.patch [moved from target/linux/bcm27xx/patches-5.4/950-0592-drm-vc4-hdmi-Remove-unused-CEC_CLOCK_DIV-define.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0587-drm-vc4-hdmi-Rename-drm_encoder-pointer-in-mode_vali.patch [moved from target/linux/bcm27xx/patches-5.4/950-0593-drm-vc4-hdmi-Rename-drm_encoder-pointer-in-mode_vali.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0588-drm-vc4-hdmi-Adjust-HSM-clock-rate-depending-on-pixe.patch [moved from target/linux/bcm27xx/patches-5.4/950-0594-drm-vc4-hdmi-Adjust-HSM-clock-rate-depending-on-pixe.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0589-drm-vc4-hdmi-Support-the-BCM2711-HDMI-controllers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0595-drm-vc4-hdmi-Support-the-BCM2711-HDMI-controllers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0590-dt-bindings-display-vc4-hdmi-Add-BCM2711-HDMI-contro.patch [moved from target/linux/bcm27xx/patches-5.4/950-0596-dt-bindings-display-vc4-hdmi-Add-BCM2711-HDMI-contro.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0591-ARM-dts-bcm2711-Enable-the-display-pipeline.patch [moved from target/linux/bcm27xx/patches-5.4/950-0597-ARM-dts-bcm2711-Enable-the-display-pipeline.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0592-DOWNSTREAM-ARM-dts-rpi4-Disable-KMS-driver-by-defaul.patch [moved from target/linux/bcm27xx/patches-5.4/950-0598-DOWNSTREAM-ARM-dts-rpi4-Disable-KMS-driver-by-defaul.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0593-dtoverlays-Add-Pi4-version-of-vc4-kms-v3d.patch [moved from target/linux/bcm27xx/patches-5.4/950-0599-dtoverlays-Add-Pi4-version-of-vc4-kms-v3d.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0594-drm-Checking-of-the-pitch-is-only-valid-for-linear-f.patch [moved from target/linux/bcm27xx/patches-5.4/950-0600-drm-Checking-of-the-pitch-is-only-valid-for-linear-f.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0595-drm-vc4-Add-support-for-DRM_FORMAT_P030-to-vc4-plane.patch [moved from target/linux/bcm27xx/patches-5.4/950-0601-drm-vc4-Add-support-for-DRM_FORMAT_P030-to-vc4-plane.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0596-Fixup-P030-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0602-Fixup-P030-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0597-drm-vc4-The-check-for-assigned-HVS-channels-is-not-a.patch [moved from target/linux/bcm27xx/patches-5.4/950-0603-drm-vc4-The-check-for-assigned-HVS-channels-is-not-a.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0598-dt-Update-v3d-to-use-firmware_clocks.patch [moved from target/linux/bcm27xx/patches-5.4/950-0604-dt-Update-v3d-to-use-firmware_clocks.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0599-drm-vc4-Reset-audio-infoframe-on-encoder_enable-if-p.patch [moved from target/linux/bcm27xx/patches-5.4/950-0605-drm-vc4-Reset-audio-infoframe-on-encoder_enable-if-p.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0600-drm-vc4-Set-the-b-frame-marker-to-the-match-ALSA-s-d.patch [moved from target/linux/bcm27xx/patches-5.4/950-0606-drm-vc4-Set-the-b-frame-marker-to-the-match-ALSA-s-d.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0601-dts-Add-reg-names-for-the-HDMI-registers-on-bcm2835.patch [moved from target/linux/bcm27xx/patches-5.4/950-0607-dts-Add-reg-names-for-the-HDMI-registers-on-bcm2835.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0602-dt-Add-HDMI-audio-dma-values-to-bcm2711.dtsi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0608-dt-Add-HDMI-audio-dma-values-to-bcm2711.dtsi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0603-drm-vc4-Use-reg-names-to-configure-HDMI-audio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0609-drm-vc4-Use-reg-names-to-configure-HDMI-audio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0604-drm-vc4-Add-audio-initialisation-for-Pi4.patch [moved from target/linux/bcm27xx/patches-5.4/950-0610-drm-vc4-Add-audio-initialisation-for-Pi4.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0605-drm-vc4-Enable-audio-on-Pi4.patch [moved from target/linux/bcm27xx/patches-5.4/950-0611-drm-vc4-Enable-audio-on-Pi4.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0606-drm-vc4-Alter-the-HDMI-state-machine-clock-calc-to-a.patch [moved from target/linux/bcm27xx/patches-5.4/950-0612-drm-vc4-Alter-the-HDMI-state-machine-clock-calc-to-a.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0607-dtoverlays-Remove-comment-about-vc4-kms-v3d-locking-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0613-dtoverlays-Remove-comment-about-vc4-kms-v3d-locking-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0608-drm-vc4-Kick-the-core-clock-up-during-a-mode-change.patch [moved from target/linux/bcm27xx/patches-5.4/950-0614-drm-vc4-Kick-the-core-clock-up-during-a-mode-change.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0609-drm-vc4-Fixup-for-firmware-KMS.patch [moved from target/linux/bcm27xx/patches-5.4/950-0615-drm-vc4-Fixup-for-firmware-KMS.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0610-drm-vc4-Fixup-plane-init-within-firmware-kms.patch [moved from target/linux/bcm27xx/patches-5.4/950-0616-drm-vc4-Fixup-plane-init-within-firmware-kms.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0611-drm-vc4-hdmi-Give-the-HDMI-audio-instances-different.patch [moved from target/linux/bcm27xx/patches-5.4/950-0617-drm-vc4-hdmi-Give-the-HDMI-audio-instances-different.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0612-i2c-brcmstb-The-interrupt-line-is-optional-so-use-pl.patch [moved from target/linux/bcm27xx/patches-5.4/950-0618-i2c-brcmstb-The-interrupt-line-is-optional-so-use-pl.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0613-dt-Drop-I2C-for-Pi4-HDMI-interfaces-to-97.5kHz.patch [moved from target/linux/bcm27xx/patches-5.4/950-0619-dt-Drop-I2C-for-Pi4-HDMI-interfaces-to-97.5kHz.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0614-overlays-Add-missing-rpi-poe-parameters.patch [moved from target/linux/bcm27xx/patches-5.4/950-0620-overlays-Add-missing-rpi-poe-parameters.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0615-vc4_hdmi_phy-Fix-offset-calculation.patch [moved from target/linux/bcm27xx/patches-5.4/950-0621-vc4_hdmi_phy-Fix-offset-calculation.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0616-overlays-Add-overlay_map.patch [moved from target/linux/bcm27xx/patches-5.4/950-0622-overlays-Add-overlay_map.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0617-overlays-Formally-rename-deprecate-old-overlays.patch [moved from target/linux/bcm27xx/patches-5.4/950-0623-overlays-Formally-rename-deprecate-old-overlays.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0618-overlays-Add-vc4-kms-v3d-pi4-to-overlay_map.patch [moved from target/linux/bcm27xx/patches-5.4/950-0624-overlays-Add-vc4-kms-v3d-pi4-to-overlay_map.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0619-Add-upstream-and-upstream-pi4-to-overlay_map.patch [moved from target/linux/bcm27xx/patches-5.4/950-0625-Add-upstream-and-upstream-pi4-to-overlay_map.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0620-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0626-clk-raspberrypi-Allow-cpufreq-driver-to-also-adjust-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0621-Add-support-for-the-AudioInjector.net-Isolated-sound.patch [moved from target/linux/bcm27xx/patches-5.4/950-0627-Add-support-for-the-AudioInjector.net-Isolated-sound.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0622-overlays-Fix-dtc-warnings-in-i2c-gpio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0628-overlays-Fix-dtc-warnings-in-i2c-gpio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0623-kbuild-Disable-gcc-plugins.patch [moved from target/linux/bcm27xx/patches-5.4/950-0629-kbuild-Disable-gcc-plugins.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0624-ASoC-ma120x0p-Add-96KHz-rate-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0630-ASoC-ma120x0p-Add-96KHz-rate-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0625-arm64-mm-reserve-CMA-and-crashkernel-in-ZONE_DMA32.patch [moved from target/linux/bcm27xx/patches-5.4/950-0631-arm64-mm-reserve-CMA-and-crashkernel-in-ZONE_DMA32.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0626-arm64-mm-Fix-initialisation-of-DMA-zones-on-non-NUMA.patch [moved from target/linux/bcm27xx/patches-5.4/950-0632-arm64-mm-Fix-initialisation-of-DMA-zones-on-non-NUMA.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0627-ARM-dts-bcm283x-Unify-CMA-configuration.patch [moved from target/linux/bcm27xx/patches-5.4/950-0633-ARM-dts-bcm283x-Unify-CMA-configuration.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0628-dma-contiguous-CMA-give-precedence-to-cmdline.patch [moved from target/linux/bcm27xx/patches-5.4/950-0634-dma-contiguous-CMA-give-precedence-to-cmdline.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0629-ARM-dts-Use-upstream-CMA-configuration.patch [moved from target/linux/bcm27xx/patches-5.4/950-0635-ARM-dts-Use-upstream-CMA-configuration.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0630-ARM-dts-overlays-Unify-overlay-CMA-handling.patch [moved from target/linux/bcm27xx/patches-5.4/950-0636-ARM-dts-overlays-Unify-overlay-CMA-handling.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0631-ARM-dts-bcm283x-Fix-vc4-s-firmware-bus-DMA-limitatio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0637-ARM-dts-bcm283x-Fix-vc4-s-firmware-bus-DMA-limitatio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0632-ARM-dts-bcm2711-Restrict-CMA-to-first-768MB.patch [moved from target/linux/bcm27xx/patches-5.4/950-0638-ARM-dts-bcm2711-Restrict-CMA-to-first-768MB.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0633-ARM-dts-Extend-SCB-bus-address-range.patch [moved from target/linux/bcm27xx/patches-5.4/950-0639-ARM-dts-Extend-SCB-bus-address-range.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0634-dts-bcm2711-Move-emmc2-to-its-own-bus.patch [moved from target/linux/bcm27xx/patches-5.4/950-0640-dts-bcm2711-Move-emmc2-to-its-own-bus.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0635-drm-vc4-hdmi-Silence-pixel-clock-error-on-EPROBE_DEF.patch [moved from target/linux/bcm27xx/patches-5.4/950-0641-drm-vc4-hdmi-Silence-pixel-clock-error-on-EPROBE_DEF.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0636-Fixes-a-problem-with-clock-settings-of-HiFiBerry-DAC.patch [moved from target/linux/bcm27xx/patches-5.4/950-0643-Fixes-a-problem-with-clock-settings-of-HiFiBerry-DAC.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0637-Documentation-media-Update-sub-device-API-intro.patch [moved from target/linux/bcm27xx/patches-5.4/950-0644-Documentation-media-Update-sub-device-API-intro.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0638-Documentation-media-Document-read-only-subdevice.patch [moved from target/linux/bcm27xx/patches-5.4/950-0645-Documentation-media-Document-read-only-subdevice.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0639-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch [moved from target/linux/bcm27xx/patches-5.4/950-0646-media-v4l2-dev-Add-v4l2_device_register_ro_subdev_no.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0640-media-bcm2835-unicam-Driver-for-CCP2-CSI2-camera-int.patch [moved from target/linux/bcm27xx/patches-5.4/950-0647-media-bcm2835-unicam-Driver-for-CCP2-CSI2-camera-int.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0641-media-uapi-v4l2-core-Add-sensor-ancillary-data-V4L2-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0648-media-uapi-v4l2-core-Add-sensor-ancillary-data-V4L2-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0642-media-uapi-Add-MEDIA_BUS_FMT_SENSOR_DATA-media-bus-f.patch [moved from target/linux/bcm27xx/patches-5.4/950-0649-media-uapi-Add-MEDIA_BUS_FMT_SENSOR_DATA-media-bus-f.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0643-media-bcm2835-unicam-Add-support-for-mulitple-device.patch [moved from target/linux/bcm27xx/patches-5.4/950-0650-media-bcm2835-unicam-Add-support-for-mulitple-device.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0644-media-bcm2835-unicam-Add-embedded-data-node.patch [moved from target/linux/bcm27xx/patches-5.4/950-0651-media-bcm2835-unicam-Add-embedded-data-node.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0645-media-bcm2835-unicam-Use-dummy-buffer-if-none-have-b.patch [moved from target/linux/bcm27xx/patches-5.4/950-0652-media-bcm2835-unicam-Use-dummy-buffer-if-none-have-b.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0646-spi-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch [moved from target/linux/bcm27xx/patches-5.4/950-0653-spi-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0647-media-i2c-imx219-Fix-power-sequence.patch [moved from target/linux/bcm27xx/patches-5.4/950-0654-media-i2c-imx219-Fix-power-sequence.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0648-media-i2c-imx219-Add-support-for-RAW8-bit-bayer-form.patch [moved from target/linux/bcm27xx/patches-5.4/950-0655-media-i2c-imx219-Add-support-for-RAW8-bit-bayer-form.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0649-media-i2c-imx219-Add-support-for-cropped-640x480-res.patch [moved from target/linux/bcm27xx/patches-5.4/950-0656-media-i2c-imx219-Add-support-for-cropped-640x480-res.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0650-media-i2c-imx219-Fix-a-bug-in-imx219_enum_frame_size.patch [moved from target/linux/bcm27xx/patches-5.4/950-0657-media-i2c-imx219-Fix-a-bug-in-imx219_enum_frame_size.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0651-media-bcm2835-unicam-Disable-event-related-ioctls-on.patch [moved from target/linux/bcm27xx/patches-5.4/950-0658-media-bcm2835-unicam-Disable-event-related-ioctls-on.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0652-media-bcm2835-unicam-Add-support-for-the-FRAME_SYNC-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0659-media-bcm2835-unicam-Add-support-for-the-FRAME_SYNC-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0653-Revert-firmware-raspberrypi-register-clk-device.patch [moved from target/linux/bcm27xx/patches-5.4/950-0660-Revert-firmware-raspberrypi-register-clk-device.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0654-media-imx219-Advertise-embedded-data-node-on-media-p.patch [moved from target/linux/bcm27xx/patches-5.4/950-0661-media-imx219-Advertise-embedded-data-node-on-media-p.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0655-dts-bcm2711-EMMC2-can-address-the-whole-first-GB.patch [moved from target/linux/bcm27xx/patches-5.4/950-0662-dts-bcm2711-EMMC2-can-address-the-whole-first-GB.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0656-driver-char-rpivid-Remove-legacy-name-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0663-driver-char-rpivid-Remove-legacy-name-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0657-driver-char-rpivid-Don-t-map-more-than-wanted.patch [moved from target/linux/bcm27xx/patches-5.4/950-0664-driver-char-rpivid-Don-t-map-more-than-wanted.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0658-dt-Implement-an-I2C-pinctrl-mux-for-BSC0.patch [moved from target/linux/bcm27xx/patches-5.4/950-0665-dt-Implement-an-I2C-pinctrl-mux-for-BSC0.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0659-dtoverlays-Update-CSI-overlays-to-use-i2c_csi_dsi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0666-dtoverlays-Update-CSI-overlays-to-use-i2c_csi_dsi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0660-dt-Update-all-mainline-bcm283x-dt-files-for-i2c0-pin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0667-dt-Update-all-mainline-bcm283x-dt-files-for-i2c0-pin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0661-ARM-dts-Create-bcm2708-rpi-b-rev1.dts.patch [moved from target/linux/bcm27xx/patches-5.4/950-0668-ARM-dts-Create-bcm2708-rpi-b-rev1.dts.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0662-dts-bcm2711-set-size-cells-2.patch [moved from target/linux/bcm27xx/patches-5.4/950-0669-dts-bcm2711-set-size-cells-2.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0663-dts-bcm2711-add-High-Peripheral-mode-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0670-dts-bcm2711-add-High-Peripheral-mode-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0664-Revert-spi-spidev-Fix-CS-polarity-if-GPIO-descriptor.patch [moved from target/linux/bcm27xx/patches-5.4/950-0671-Revert-spi-spidev-Fix-CS-polarity-if-GPIO-descriptor.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0665-spi-use_gpio_descriptor-fixup-moved-to-spi_setup.patch [moved from target/linux/bcm27xx/patches-5.4/950-0672-spi-use_gpio_descriptor-fixup-moved-to-spi_setup.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0666-overlays-rpivid-v4l2-also-needs-size-cells-2.patch [moved from target/linux/bcm27xx/patches-5.4/950-0673-overlays-rpivid-v4l2-also-needs-size-cells-2.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0667-media-bcm2835-unicam-Re-fetch-mbus-code-from-subdev-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0674-media-bcm2835-unicam-Re-fetch-mbus-code-from-subdev-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0668-uapi-bcm2835-isp-Add-bcm2835-isp-uapi-header-file.patch [moved from target/linux/bcm27xx/patches-5.4/950-0675-uapi-bcm2835-isp-Add-bcm2835-isp-uapi-header-file.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0669-media-uapi-v4l2-core-Add-ISP-statistics-output-V4L2-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0676-media-uapi-v4l2-core-Add-ISP-statistics-output-V4L2-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0670-media-uapi-v4l-ctrls-Add-CID-base-for-the-bcm2835-is.patch [moved from target/linux/bcm27xx/patches-5.4/950-0677-media-uapi-v4l-ctrls-Add-CID-base-for-the-bcm2835-is.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0671-staging-mmal-vchiq-Fix-formatting-errors-in-mmal_par.patch [moved from target/linux/bcm27xx/patches-5.4/950-0678-staging-mmal-vchiq-Fix-formatting-errors-in-mmal_par.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0672-staging-vc04_services-ISP-Add-a-more-complex-ISP-pro.patch [moved from target/linux/bcm27xx/patches-5.4/950-0679-staging-vc04_services-ISP-Add-a-more-complex-ISP-pro.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0673-staging-vchiq-Load-bcm2835_isp-driver-from-vchiq.patch [moved from target/linux/bcm27xx/patches-5.4/950-0680-staging-vchiq-Load-bcm2835_isp-driver-from-vchiq.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0674-vc4_hvs-Mark-core-clock-as-optional.patch [moved from target/linux/bcm27xx/patches-5.4/950-0681-vc4_hvs-Mark-core-clock-as-optional.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0675-vc4_hdmi-BCM2835-requires-a-fixed-hsm-clock-for-CEC-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0682-vc4_hdmi-BCM2835-requires-a-fixed-hsm-clock-for-CEC-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0676-media-i2c-imx219-Implement-get_selection.patch [moved from target/linux/bcm27xx/patches-5.4/950-0683-media-i2c-imx219-Implement-get_selection.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0677-media-i2c-ov5647-Add-support-for-g_selection-to-refl.patch [moved from target/linux/bcm27xx/patches-5.4/950-0684-media-i2c-ov5647-Add-support-for-g_selection-to-refl.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0678-media-i2c-ov5467-Fixup-error-path-to-release-mutex.patch [moved from target/linux/bcm27xx/patches-5.4/950-0685-media-i2c-ov5467-Fixup-error-path-to-release-mutex.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0679-media-i2c-ov5647-Support-V4L2_CID_PIXEL_RATE.patch [moved from target/linux/bcm27xx/patches-5.4/950-0686-media-i2c-ov5647-Support-V4L2_CID_PIXEL_RATE.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0680-media-i2c-ov5647-Set-V4L2_SUBDEV_FL_HAS_EVENTS-flag.patch [moved from target/linux/bcm27xx/patches-5.4/950-0687-media-i2c-ov5647-Set-V4L2_SUBDEV_FL_HAS_EVENTS-flag.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0681-media-i2c-ov5647-Add-support-for-V4L2_CID_VBLANK.patch [moved from target/linux/bcm27xx/patches-5.4/950-0688-media-i2c-ov5647-Add-support-for-V4L2_CID_VBLANK.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0682-media-i2c-ov5647-Neither-analogue-gain-nor-exposure-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0689-media-i2c-ov5647-Neither-analogue-gain-nor-exposure-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0683-media-i2c-ov5647-Use-member-names-in-mode-tables.patch [moved from target/linux/bcm27xx/patches-5.4/950-0690-media-i2c-ov5647-Use-member-names-in-mode-tables.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0684-media-i2c-ov5647-Advertise-the-correct-exposure-rang.patch [moved from target/linux/bcm27xx/patches-5.4/950-0691-media-i2c-ov5647-Advertise-the-correct-exposure-rang.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0685-media-i2c-imx219-Declare-that-the-driver-can-create-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0692-media-i2c-imx219-Declare-that-the-driver-can-create-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0686-media-bcm2835-unicam-Add-support-for-VIDIOC_-S-G-_SE.patch [moved from target/linux/bcm27xx/patches-5.4/950-0693-media-bcm2835-unicam-Add-support-for-VIDIOC_-S-G-_SE.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0687-media-bcm2835-unicam-Do-not-stop-streaming-in-unicam.patch [moved from target/linux/bcm27xx/patches-5.4/950-0694-media-bcm2835-unicam-Do-not-stop-streaming-in-unicam.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0688-media-bcm2835-unicam-Fix-reference-counting-in-unica.patch [moved from target/linux/bcm27xx/patches-5.4/950-0695-media-bcm2835-unicam-Fix-reference-counting-in-unica.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0689-staging-vc04_services-ISP-Add-enum_framesizes-ioctl.patch [moved from target/linux/bcm27xx/patches-5.4/950-0696-staging-vc04_services-ISP-Add-enum_framesizes-ioctl.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0690-SQUASH-spi-Demote-SPI_CS_HIGH-warning-to-KERN_DEBUG.patch [moved from target/linux/bcm27xx/patches-5.4/950-0697-SQUASH-spi-Demote-SPI_CS_HIGH-warning-to-KERN_DEBUG.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0691-bcm2835-dma-Add-proper-40-bit-DMA-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0698-bcm2835-dma-Add-proper-40-bit-DMA-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0692-ARM-dts-bcm2711-Allow-40-bit-DMA-for-SPI.patch [moved from target/linux/bcm27xx/patches-5.4/950-0699-ARM-dts-bcm2711-Allow-40-bit-DMA-for-SPI.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0693-overlays-Make-the-i2c-gpio-overlay-safe-again.patch [moved from target/linux/bcm27xx/patches-5.4/950-0700-overlays-Make-the-i2c-gpio-overlay-safe-again.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0694-staging-vc04_services-isp-Remove-duplicated-initiali.patch [moved from target/linux/bcm27xx/patches-5.4/950-0701-staging-vc04_services-isp-Remove-duplicated-initiali.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0695-staging-vc04_services-isp-Make-all-references-to-bcm.patch [moved from target/linux/bcm27xx/patches-5.4/950-0702-staging-vc04_services-isp-Make-all-references-to-bcm.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0696-vc4_hdmi_phy-Fix-typo-in-phy_get_cp_current.patch [moved from target/linux/bcm27xx/patches-5.4/950-0704-vc4_hdmi_phy-Fix-typo-in-phy_get_cp_current.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0697-overlays-Make-use-of-intra-overlay-fragments.patch [moved from target/linux/bcm27xx/patches-5.4/950-0705-overlays-Make-use-of-intra-overlay-fragments.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0698-media-i2c-tc358743-Fix-fallthrough-warning.patch [moved from target/linux/bcm27xx/patches-5.4/950-0706-media-i2c-tc358743-Fix-fallthrough-warning.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0699-media-bcm2835-unicam-Fix-uninitialized-warning.patch [moved from target/linux/bcm27xx/patches-5.4/950-0707-media-bcm2835-unicam-Fix-uninitialized-warning.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0700-video-bcm2708_fb-Disable-FB-if-no-displays-found.patch [moved from target/linux/bcm27xx/patches-5.4/950-0708-video-bcm2708_fb-Disable-FB-if-no-displays-found.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0701-overlays-sc16is752-spi1-Add-xtal-parameter.patch [moved from target/linux/bcm27xx/patches-5.4/950-0709-overlays-sc16is752-spi1-Add-xtal-parameter.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0702-vc4_hdmi-Fix-register-offset-when-sending-longer-CEC.patch [moved from target/linux/bcm27xx/patches-5.4/950-0710-vc4_hdmi-Fix-register-offset-when-sending-longer-CEC.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0703-overlays-gpio-keys-Avoid-open-drain-warnings.patch [deleted file]
target/linux/bcm27xx/patches-5.4/950-0703-vc4_hdmi-Fix-up-CEC-registers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0711-vc4_hdmi-Fix-up-CEC-registers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0704-vc4_hdmi_regs-Add-Intr2-register-block.patch [moved from target/linux/bcm27xx/patches-5.4/950-0712-vc4_hdmi_regs-Add-Intr2-register-block.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0705-vc4_hdmi_regs-Make-interrupt-mask-variant-specific.patch [moved from target/linux/bcm27xx/patches-5.4/950-0713-vc4_hdmi_regs-Make-interrupt-mask-variant-specific.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0706-vc4_hdmi-Make-irq-shared.patch [moved from target/linux/bcm27xx/patches-5.4/950-0714-vc4_hdmi-Make-irq-shared.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0707-vc4_hdmi-Adjust-CEC-ref-clock-based-on-its-input-clo.patch [moved from target/linux/bcm27xx/patches-5.4/950-0715-vc4_hdmi-Adjust-CEC-ref-clock-based-on-its-input-clo.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0708-vc4_hdmi-Remove-cec_available-flag-as-always-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0716-vc4_hdmi-Remove-cec_available-flag-as-always-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0709-overlays-tc358743-Use-intra-overlay-fragments.patch [moved from target/linux/bcm27xx/patches-5.4/950-0717-overlays-tc358743-Use-intra-overlay-fragments.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0710-overlays-Move-fixed-clock-nodes-to-the-root.patch [moved from target/linux/bcm27xx/patches-5.4/950-0718-overlays-Move-fixed-clock-nodes-to-the-root.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0711-raspberrypi-dts-Switch-to-discrete-ALSA-devices.patch [moved from target/linux/bcm27xx/patches-5.4/950-0719-raspberrypi-dts-Switch-to-discrete-ALSA-devices.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0712-dt-bindings-media-i2c-Add-IMX477-CMOS-sensor-binding.patch [moved from target/linux/bcm27xx/patches-5.4/950-0720-dt-bindings-media-i2c-Add-IMX477-CMOS-sensor-binding.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0713-dtoverlays-Add-IMX477-sensor-overlay.patch [moved from target/linux/bcm27xx/patches-5.4/950-0721-dtoverlays-Add-IMX477-sensor-overlay.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0714-media-i2c-Add-driver-for-Sony-IMX477-sensor.patch [moved from target/linux/bcm27xx/patches-5.4/950-0722-media-i2c-Add-driver-for-Sony-IMX477-sensor.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0715-media-i2c-imx477-Add-support-for-adaptive-frame-cont.patch [moved from target/linux/bcm27xx/patches-5.4/950-0723-media-i2c-imx477-Add-support-for-adaptive-frame-cont.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0716-udmabuf-Remove-deleted-map-unmap-handlers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0724-udmabuf-Remove-deleted-map-unmap-handlers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0717-udmabuf-use-cache_sgt_mapping-option.patch [moved from target/linux/bcm27xx/patches-5.4/950-0725-udmabuf-use-cache_sgt_mapping-option.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0718-udmabuf-add-a-pointer-to-the-miscdevice-in-dma-buf-p.patch [moved from target/linux/bcm27xx/patches-5.4/950-0726-udmabuf-add-a-pointer-to-the-miscdevice-in-dma-buf-p.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0719-udmabuf-separate-out-creating-destroying-scatter-tab.patch [moved from target/linux/bcm27xx/patches-5.4/950-0727-udmabuf-separate-out-creating-destroying-scatter-tab.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0720-udmabuf-implement-begin_cpu_access-end_cpu_access-ho.patch [moved from target/linux/bcm27xx/patches-5.4/950-0728-udmabuf-implement-begin_cpu_access-end_cpu_access-ho.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0721-udmabuf-fix-dma-buf-cpu-access.patch [moved from target/linux/bcm27xx/patches-5.4/950-0729-udmabuf-fix-dma-buf-cpu-access.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0722-dma-buf-Add-dma-buf-heaps-framework.patch [moved from target/linux/bcm27xx/patches-5.4/950-0730-dma-buf-Add-dma-buf-heaps-framework.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0723-dma-buf-heaps-Add-heap-helpers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0731-dma-buf-heaps-Add-heap-helpers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0724-dma-buf-heaps-Add-system-heap-to-dmabuf-heaps.patch [moved from target/linux/bcm27xx/patches-5.4/950-0732-dma-buf-heaps-Add-system-heap-to-dmabuf-heaps.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0725-dma-buf-heaps-Add-CMA-heap-to-dmabuf-heaps.patch [moved from target/linux/bcm27xx/patches-5.4/950-0733-dma-buf-heaps-Add-CMA-heap-to-dmabuf-heaps.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0726-kselftests-Add-dma-heap-test.patch [moved from target/linux/bcm27xx/patches-5.4/950-0734-kselftests-Add-dma-heap-test.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0727-dma-buf-heaps-Use-_IOCTL_-for-userspace-IOCTL-identi.patch [moved from target/linux/bcm27xx/patches-5.4/950-0735-dma-buf-heaps-Use-_IOCTL_-for-userspace-IOCTL-identi.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0728-dma-buf-heaps-Remove-redundant-heap-identifier-from-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0736-dma-buf-heaps-Remove-redundant-heap-identifier-from-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0729-dma-buf-fix-resource-leak-on-ENOTTY-error-return-pat.patch [moved from target/linux/bcm27xx/patches-5.4/950-0737-dma-buf-fix-resource-leak-on-ENOTTY-error-return-pat.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0730-dma-heap-Make-the-symbol-dma_heap_ioctl_cmds-static.patch [moved from target/linux/bcm27xx/patches-5.4/950-0738-dma-heap-Make-the-symbol-dma_heap_ioctl_cmds-static.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0731-ARM-dts-Enable-firmware-clocks-on-all-Pis.patch [moved from target/linux/bcm27xx/patches-5.4/950-0739-ARM-dts-Enable-firmware-clocks-on-all-Pis.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0732-media-bcm2835-unicam-Always-service-interrupts.patch [moved from target/linux/bcm27xx/patches-5.4/950-0740-media-bcm2835-unicam-Always-service-interrupts.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0733-sc16is7xx-Fix-for-hardware-flow-control.patch [moved from target/linux/bcm27xx/patches-5.4/950-0741-sc16is7xx-Fix-for-hardware-flow-control.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0734-drm-vc4-Fix-VIC-usage-with-Broadcast-RGB.patch [moved from target/linux/bcm27xx/patches-5.4/950-0742-drm-vc4-Fix-VIC-usage-with-Broadcast-RGB.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0735-staging-vc04_services-mmal-vchiq-Update-parameters-l.patch [moved from target/linux/bcm27xx/patches-5.4/950-0743-staging-vc04_services-mmal-vchiq-Update-parameters-l.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0736-staging-vc04_services-bcm2835-codec-Request-headers-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0744-staging-vc04_services-bcm2835-codec-Request-headers-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0737-staging-vc04_services-bcm2835-codec-Avoid-fragmentin.patch [moved from target/linux/bcm27xx/patches-5.4/950-0745-staging-vc04_services-bcm2835-codec-Avoid-fragmentin.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0738-staging-vc04_services-bcm2835-camera-Request-headers.patch [moved from target/linux/bcm27xx/patches-5.4/950-0746-staging-vc04_services-bcm2835-camera-Request-headers.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0739-overlays-Fix-audio-parameter-of-vc4-kms-v3d.patch [moved from target/linux/bcm27xx/patches-5.4/950-0747-overlays-Fix-audio-parameter-of-vc4-kms-v3d.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0740-Switch-to-snd_soc_dai_set_bclk_ratio.patch [moved from target/linux/bcm27xx/patches-5.4/950-0748-Switch-to-snd_soc_dai_set_bclk_ratio.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0741-media-bcm2835-unicam-Retain-packing-information-on-G.patch [moved from target/linux/bcm27xx/patches-5.4/950-0749-media-bcm2835-unicam-Retain-packing-information-on-G.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0742-zswap-Defer-zswap-initialisation.patch [moved from target/linux/bcm27xx/patches-5.4/950-0750-zswap-Defer-zswap-initialisation.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0743-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0751-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0744-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch [moved from target/linux/bcm27xx/patches-5.4/950-0752-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0745-media-i2c-imx477-Return-correct-result-on-sensor-id-.patch [moved from target/linux/bcm27xx/patches-5.4/950-0753-media-i2c-imx477-Return-correct-result-on-sensor-id-.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0746-staging-vchiq_arm-Clean-up-40-bit-DMA-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0754-staging-vchiq_arm-Clean-up-40-bit-DMA-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0747-ARM-dts-Update-for-new-VCHIQ-BCM2711-DMA-support.patch [moved from target/linux/bcm27xx/patches-5.4/950-0755-ARM-dts-Update-for-new-VCHIQ-BCM2711-DMA-support.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0748-media-bcm2835-unicam-change-minimum-number-of-vb2_qu.patch [moved from target/linux/bcm27xx/patches-5.4/950-0756-media-bcm2835-unicam-change-minimum-number-of-vb2_qu.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0749-dt-bindings-Add-Broadcom-AVS-RO-thermal.patch [moved from target/linux/bcm27xx/patches-5.4/950-0757-dt-bindings-Add-Broadcom-AVS-RO-thermal.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0750-thermal-Add-BCM2711-thermal-driver.patch [moved from target/linux/bcm27xx/patches-5.4/950-0758-thermal-Add-BCM2711-thermal-driver.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0751-ARM-dts-bcm2711-Enable-thermal.patch [moved from target/linux/bcm27xx/patches-5.4/950-0759-ARM-dts-bcm2711-Enable-thermal.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0752-ARM-dts-bcm2711-rpi-Remove-downstream-thermal-sensor.patch [moved from target/linux/bcm27xx/patches-5.4/950-0760-ARM-dts-bcm2711-rpi-Remove-downstream-thermal-sensor.patch with 100% similarity]
target/linux/bcm27xx/patches-5.4/950-0753-overlays-i2c-rtc-Fix-trickle-resistor-ohms-param.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0754-overlays-gpio-shutdown-Add-information-for-SysV-init.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0755-overlays-gpio-shutdown-Add-information-for-Raspberry.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0756-overlays-Add-spi0-overlay-to-support-sc16is752.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0757-overlays-i2c-rtc-gpio-Fix-trickle-resistor-ohms-para.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0758-media-bcm2835-isp-fix-bytes-per-line-calculations-fo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0759-Add-Micro-Crystal-RV-1805-to-i2c-rtc-overlays.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0760-vc4-Set-driver_name-for-card.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0761-staging-vchiq_arm-Use-g_dma_dev-for-dma_unmap_sg.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0762-vc4-cec-Restore-cec-physical-address-on-reconnect.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0763-snd_bcm2835-disable-HDMI-audio-when-vc4-is-used-3640.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0764-overlays-i2c-gpio-Avoid-open-drain-warnings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0765-overlays-Update-upstream-overlays-after-vc4-kms-v3d-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0768-w1_therm-adding-ext_power-sysfs-entry.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0769-w1_therm-adding-resolution-sysfs-entry.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0770-w1_therm-adding-eeprom-sysfs-entry.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0772-w1_therm-adding-alarm-sysfs-entry.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0774-w1_therm-Free-the-correct-variable.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0775-w1_therm-remove-redundant-assignments-to-variable-re.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0776-PCI-brcmstb-Assert-fundamental-reset-on-initializati.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0777-clk-rpi-Adjust-DT-binding-to-match-upstream.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0778-clk-bcm-rpi-Add-an-enum-for-the-firmware-clocks.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0779-clk-bcm-rpi-Use-CCF-boundaries-instead-of-rolling-ou.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0780-clk-bcm-rpi-Give-firmware-clocks-a-name.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0781-clk-bcm-rpi-Remove-the-quirks-for-the-CPU-clock.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0782-clk-rpi-Only-register-a-few-firmware-clocks.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0783-clk-rpi-Fix-compatible-indentation.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0784-SQUASH-dts-Fix-firmware-clocks-support.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0786-PCI-brcmstb-Add-DT-property-to-control-L1SS.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0787-ARM-dts-Set-brcm-enable-l1ss-for-CM4.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0788-Revert-SQUASH-Fix-spi-driver-compiler-warnings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0789-Revert-spi-spi-bcm2835-Disable-forced-software-CS.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0790-media-irs1125-Using-i2c_transfer-for-ic2-reads.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0791-media-irs1125-Refactoring-and-debug-messages.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0792-media-irs1125-Atomic-access-to-imager-reconfiguratio.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0794-staging-bcm2835-audio-Add-missing-MODULE_ALIAS.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0795-media-v4l2-subdev-Introduce-get-set-_mbus_config-pad.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0796-media-i2c-Use-the-new-get_mbus_config-pad-op.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0797-media-i2c-ov6650-Use-new-get-set-_mbus_config-ops.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0799-media-v4l2-subdev-Remove-s-g-_mbus_config-video-ops.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0800-staging-media-imx-Update-TODO-entry.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0801-media-i2c-adv748x-Adjust-TXA-data-lanes-number.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0802-media-i2c-adv748x-Implement-get_mbus_config.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0804-drivers-media-Remove-the-downstream-version-of-bcm28.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0805-include-media-Add-vfl_devnode_type-of-VFL_TYPE_VIDEO.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0806-media-bcm2835-unicam-Driver-for-CCP2-CSI2-camera-int.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0807-media-bcm2835-unicam-Add-support-for-get_mbus_config.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0808-media-bcm2835-unicam-Always-service-interrupts.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0809-media-bcm2835-unicam-Fix-uninitialized-warning.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0810-media-bcm2835-unicam-Fixup-review-comments-from-Hans.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0811-media-bcm2835-unicam-Retain-packing-information-on-G.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0812-media-bcm2835-unicam-change-minimum-number-of-vb2_qu.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0813-dt-dtoverlays-Fix-up-base-DT-and-overlays-for-update.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0814-media-bcm2835-unicam-Avoid-gcc-warning-over-0-on-end.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0815-media-dt-bindings-media-i2c-Add-IMX290-CMOS-sensor-b.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0816-media-i2c-Add-IMX290-CMOS-image-sensor-driver.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0817-media-i2c-imx290-set-the-format-before-VIDIOC_SUBDEV.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0818-media-i2c-imx290-fix-the-order-of-the-args-in-SET_RU.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0819-media-i2c-imx290-fix-reset-GPIO-pin-handling.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0820-media-i2c-imx290-Add-support-for-2-data-lanes.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0821-media-i2c-imx290-Add-configurable-link-frequency-and.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0822-media-i2c-imx290-Add-support-for-test-pattern-genera.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0823-media-i2c-imx290-Add-RAW12-mode-support.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0824-media-i2c-imx290-Add-support-to-enumerate-all-frame-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0825-media-i2c-imx290-Move-the-settle-time-delay-out-of-l.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0826-media-i2c-imx290-set-bus_type-before-calling-v4l2_fw.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0828-media-i2c-imx290-Correct-range-for-V4L2_CID_GAIN-to-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0830-media-i2c-imx290-Add-support-for-V4L2_CID_VBLANK.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0831-media-i2c-imx290-Add-exposure-control-to-the-driver.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0832-media-i2c-imx290-Add-H-and-V-flip-controls.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0833-media-dt-bindings-media-i2c-Add-mono-version-to-IMX2.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0834-media-i2c-imx290-Add-support-for-the-mono-sensor-var.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0835-media-i2c-imx290-Switch-set_hmax-to-use-imx290_write.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0836-dtoverlays-Add-an-overlay-for-the-Sony-IMX290-image-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0837-vc4_hdmi-Set-HD_CTL_WHOLSMP-and-HD_CTL_CHALIGN_SET.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0838-staging-vc04_services-isp-Fixup-g-s_selection-implem.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0839-staging-vc04_services-isp-Reorder-operations-during-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0840-uapi-bcm2835-isp-Fixups-for-bcm2835-isp-uapi-structu.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0841-ARM-dts-Add-Bluetooth-nodes-for-Raspberry-Pi.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0842-drm-vc4-Allow-interlaced-HDMI-modes-from-FKMS.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0843-serial-8250-bcm2835aux-defer-if-clock-is-zero.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0844-media-v4l-Add-14-bit-raw-bayer-pixel-formats.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0845-media-v4l-Add-14-bit-raw-greyscale-pixel-format.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0846-media-v4l-Add-1X14-14-bit-greyscale-media-bus-code-d.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0847-media-Add-a-pixel-format-for-MIPI-packed-12bit-luma-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0848-media-Add-a-pixel-format-for-MIPI-packed-14bit-luma-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0849-staging-vc04_services-isp-Add-support-for-14bit-Baye.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0850-staging-vc04_services-isp-Add-monochrome-image-forma.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0851-staging-vc04_services-isp-Increase-the-number-of-sup.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0852-staging-vc04_services-codec-Increase-the-number-of-s.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0853-staging-vc04_services-codec-Add-support-for-mono-for.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0854-staging-vc04_services-codec-Add-support-for-14bit-Ba.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0855-media-bcm2835-unicam-Add-support-for-12bit-mono-pack.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0856-media-bcm2835-unicam-Add-support-for-14bit-mono-sour.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0857-media-bcm2835-unicam-Add-support-for-unpacked-14bit-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0858-overlays-Fix-miniuart-bt-krnbt-parameter.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0859-drm-vc4-Make-FKMS-max-refresh-rate-a-module-paramete.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0860-drm-vc4-FKMS-Block-modes-with-odd-horizontal-timing-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0861-dt-Use-rpi-firmware-kms-2711-on-2711-platforms.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0862-drm-vc4-FKMS-Put-includes-in-alphabetical-order-and-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0863-irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0864-dtoverlays-Fixup-imx219-and-imx477-overlays-due-to-p.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0865-overlays-rpi-ft5406-Fix-boolean-parameters.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0866-ARM-dts-Copy-kernel-BT-changes-to-CM4.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0867-ARM-dts-Make-bcm2711-dts-more-like-5.7.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0868-bcm2835-dma-Add-NO_WAIT_RESP-flag.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0869-ARM-dts-Restore-the-old-2711-scb-ranges-property.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0870-media-i2c-add-ov9281-driver.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0871-media-i2c-ov9281-fix-mclk-issue-when-probe-multiple-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0872-media-i2c-ov9281-add-enum_frame_interval-function-fo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0873-media-i2c-ov9281-Fixup-for-recent-kernel-releases-an.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0874-media-i2c-ov9281-Read-chip-ID-via-2-reads.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0875-dtoverlay-Add-overlay-for-Omnivision-OV9281-image-se.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0876-Bluetooth-hci_bcm-Fix-RTS-handling-during-startup.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0877-Bluetooth-hci_bcm-Add-compatible-string-for-BCM43540.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0878-Bluetooth-btbcm-Add-entry-for-BCM4335A0-UART-bluetoo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0879-Bluetooth-hci_bcm-Disallow-set_baudrate-for-BCM4354.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0880-Bluetooth-btbcm-Support-pcm-configuration.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0881-Bluetooth-hci_bcm-Support-pcm-params-in-dts.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0882-Bluetooth-hci_bcm-Drive-RTS-only-for-BCM43438.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0883-Enhances-the-DAC-driver-to-control-the-optional-head.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0884-ARM-dts-hifiberry-dacplus-headphone-amp-support.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0885-media-i2c-imx290-Explicitly-set-v-h-blank-on-mode-ch.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0886-media-i2c-imx290-Add-support-for-g_selection-to-repo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0887-media-i2c-imx290-Set-the-colorspace-fields-in-the-fo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0888-media-bcm2835-unicam-Reinstate-V4L2_CAP_READWRITE-in.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0889-media-bcm2835-unicam-Ensure-type-is-VIDEO_CAPTURE-in.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0890-dtoverlays-Create-an-overlay-for-the-Omnivision-OV72.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0891-vc4_hdmi-Set-HDMI_MAI_FMT.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0892-drm-vc4-add-iec958-controls-to-vc4_hdmi.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0893-drm-vc4-move-setup-from-hw_params-to-prepare.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0894-drm-vc4-enable-HBR-MAI-format-on-HBR-streams.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0895-vc4_hdmi-Remove-firmware-logic-for-MAI-threshold-set.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0896-vc_hdmi-Set-VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0897-dts-Enable-NO_WAIT_RESP-for-hdmi-audio-dma.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0898-SQUASH-dts-Further-simplify-firmware-clocks.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0899-media-bcm2835-unicam-Set-VPU-min-clock-freq-to-250Mh.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0900-dt-bindings-bcm2835-unicam-Update-documentation-with.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0901-correct-SND_SOC_DAILINK_DEFS.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0902-media-dt-bindings-video-interfaces-Document-orientat.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0903-media-dt-bindings-video-interface-Replace-rotation-d.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0904-media-v4l2-ctrl-Document-V4L2_CID_CAMERA_ORIENTATION.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0905-media-v4l2-ctrl-Document-V4L2_CID_CAMERA_SENSOR_ROTA.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0906-media-v4l2-ctrls-Add-camera-orientation-and-rotation.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0907-media-v4l2-fwnode-Add-helper-to-parse-device-propert.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0908-media-v4l2-ctrls-Add-helper-to-register-properties.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0909-media-i2c-ov5647-Parse-and-register-properties.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0910-media-i2c-imx219-Parse-and-register-properties.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0911-media-i2c-imx477-Parse-and-register-properties.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0912-dt-dtoverlays-ov5647-Add-parameter-to-set-camera-mod.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0913-dt-dtoverlays-imx219-Add-parameter-to-set-camera-mod.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0914-dt-dtoverlays-imx477-Add-parameter-to-set-camera-mod.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0915-drm-vc4-Add-DRM_MODE_FLAG_DBLCLK-support-to-vc4-fkms.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0916-leds-Add-the-actpwr-trigger.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0917-ARM-dts-Select-the-actpwr-LED-trigger-on-Zeroes.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0918-staging-vc04_services-isp-Rework-lens-shading-to-tak.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0919-Mute-bug-fix-for-the-Audioinjector.net-isolated-soun.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0920-vc4-Report-channel-mapping-back-to-userspace.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0921-SQUASH-leds-actpwr-delete-unused-variable.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0922-staging-vchiq_arm-children-inherit-DMA-config.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0923-ARM-dts-2711-DMA-can-address-36-bits.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0924-bcm2835-dma-Advertise-the-full-DMA-range.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0925-ARM-dts-Add-UART-skip-init-properties-for-U-boot.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0926-drm-vc4-Remove-UIF-from-the-list-of-modifiers-return.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0927-ARM-proc-v7-Force-misalignment-of-early-stmia.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0928-overlays-Fix-sc16is75x-overlays-w.r.t.-serdev.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0929-overlays-Delete-spi0-hw-cs.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0930-backlight-gpio-Explicitly-set-the-direction-of-the-G.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0931-overlays-Add-maxtherm-overlay-for-MAX6675-31855.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0932-dtoverlays-Add-the-iio_hwmon-driver-to-correct-ADC-i.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0933-dts-bcm2711-Disable-DVP-by-default.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0934-ARM-dts-Add-required-USB-power-domain-for-XCHI.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0935-overlays-Regenerate-upstream-pi4.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0936-drm-vc4-Increase-the-number-of-planes-per-crtc-in-FK.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0937-drm-vc4-Set-the-possible-crtcs-mask-correctly-for-pl.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0938-staging-vc04_services-codec-Fix-incorrect-buffer-cle.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0939-staging-vc04_service-codec-Allow-start_streaming-to-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0940-staging-vc04_services-codec-Fix-component-enable-dis.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0941-update-rpi-display-overlay.dts-pins-for-5.4.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0942-Bluetooth-btrtl-Add-support-for-RTL8761B.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0943-dtoverlays-Add-overlay-for-the-PCA953x-family-of-GPI.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0944-rtc-rv3028-Write-BSM-and-TCE-TCR-to-EEPROM.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0945-rtc-rv3028-Refresh-RAM-on-EEPROM-write.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0946-dt-overlays-Add-PiFace-Digital-Device-Tree-Overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0947-overlays-Updated-MCP3008-compatible-strings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0948-RESET_CONTROLLER-needs-to-be-activated-to-compile-Br.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0949-media-dvbsky-use-a-single-mutex-and-state-buffers-fo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0950-ARM-dts-bcm2711-Enable-support-for-DDR52-eMMC.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0951-staging-vc04_services-ISP-Fix-dmabuf-error-check-in-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0952-ARM-dts-bcm2708.dtsi-Don-t-delete-the-cpus-node.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0953-ARM-dts-bcm2835-Use-the-L2-non-allocating-alias.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0954-media-bcm2835-unicam-Drop-WARN-on-uing-direct-cache-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0955-media-i2c-tc358743-Only-allow-supported-pixel-fmts-i.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0956-media-i2c-ov9281-Add-support-for-8-bit-readout.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0957-overlays-Add-spi0-1cs-and-spi0-2cs.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0958-overlays-Fix-error-in-README.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0959-overlays-Minor-README-correction.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0960-staging-fbtft-Add-support-for-display-variants.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0961-overlays-Add-adafruit18-and-sainsmart18-overlays.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0962-ARM-dts-Limit-BT-modem-baud-rate-on-3B.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0963-overlays-Update-i2c0-overlay-to-disable-the-i2c0mux.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0964-dt-Remove-duplicate-assignment-for-i2c0-pinctrl-conf.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0965-overlays-Add-option-for-composite-to-vc4-kms-v3d-pi4.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0966-minor-typo-in-directions.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0967-overlays-Regenerate-upstream-pi4-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0968-overlays-Add-parameters-to-adafruit18-sainsmart18.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0969-rpivid_h265-Fix-width-height-typo.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0970-overlays-Add-extra-CMA-sizes-up-to-512M.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0971-overlays-Add-note-to-BCM2711-overlays.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0972-overlays-adafruit18-sainsmart18-default-bgr-to-off.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0973-net-bcmgenet-Reset-RBUF-on-first-open.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0974-ASoC-cs42xx8-Only-define-cs42xx8_of_match-once.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0975-staging-bcm2835-codec-Use-a-define-the-completion-ti.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0976-staging-bcm2835-codec-Correct-buffer-number-change-o.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0977-USB-gadget-f_hid-avoid-crashes-and-log-spam.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0978-Update-hy28b-overlay.dts.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0979-overlays-Update-display-GPIO-declarations.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0980-SQUASH-USB-gadget-f_hid-remove-more-spam.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0981-overlays-Add-sd3078-to-the-i2c-rtc-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0982-dwc_otg-initialise-sched_frame-for-periodic-QHs-that.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0983-staging-bcm2835-camera-Replace-deprecated-V4L2_PIX_F.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0984-staging-bcm2835-codec-Replace-deprecated-V4L2_PIX_FM.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0985-ARM-bcm2711-rpi.dts-Unlock-DMA-channels-9-10.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0986-gpio-Add-gpio-fsm-driver.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0987-overlays-Add-fsm-demo-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0988-overlays-Add-ghost-amp-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0989-Bluetooth-Disable-High-Speed-by-default.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0990-Fixes-a-problem-when-module-probes-before-i2c-module.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0991-uapi-Update-V4L2_CID_USER_BCM2835_ISP_BASE-due-to-up.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0992-dtoverlays-Correct-CSI2-settings-for-ov9281.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0993-xhci-quirks-add-link-TRB-quirk-for-VL805.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0994-dts-Add-CM4-to-arm64-dt-files.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0995-dts-Tidy-the-Raspberry-Pi-Makefile-entries.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0996-staging-bcm2835-audio-Add-disable-headphones-flag.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0997-ARM-dts-Disable-headphone-audio-on-Zeroes-CM4.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0998-overlays-Enable-headphone-audio-in-audremap.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0999-rpisense-fb-Set-pseudo_pallete-to-prevent-crash-on-f.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1000-PiFi-40-Devicetree-files.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1001-PiFi-40-driver-Makefile-and-Kconfig.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1002-dwc_otg-Minimise-header-and-fix-build-warnings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1003-gpio-fsm-Fix-a-build-warning.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1004-rpivid_h625-Fix-build-warnings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1005-dwc_otg-Fix-more-build-warnings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1006-bcm2708_fb-Fix-a-build-warning.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1007-bcm2835-pcm-Fix-up-multichannel-pcm-audio.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1008-watchdog-bcm2835-Ignore-params-after-the-partition-n.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1009-firmware-raspberrypi-Add-support-for-tryonce-reboot-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1010-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1011-phy-broadcom-Add-bcm54213pe-configuration.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1012-Allo-boss2-driver.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1013-Add-allo-boss2-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1014-Revert-mailbox-avoid-timer-start-from-callback.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1015-ARM-dts-Add-bcm2711-rpi-400.dts.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1016-overlays-Deprecate-and-delete-the-sdtweak-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1017-overlays-Complete-the-sdtweak-excision.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1018-ARM-dts-bcm27xx-Remove-enable_headphones-setting.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1019-staging-vcsm-cma-Fix-memory-leak-from-not-detaching-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1020-Update-Allo-Piano-Dac-Driver-for-5.4.y-kernels.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1021-Overlay-Update-Allo-Piano-Plus-dac-driver-for-5.4.y-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1022-Update-volume-controls-in-Allo-Piano-Dac-Plus.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1023-media-i2c-imx219-Selection-compliance-fixes.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1024-media-bcm2835-unicam-Correctly-handle-error-propagat.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1025-media-bcm2835-unicam-Return-early-from-stop_streamin.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1026-media-bcm2835-unicam-Clear-clock-state-when-stopping.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1027-ARM-dts-CM4-audio-pins-are-not-connected.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1028-overlays-Add-PCF85063-and-PCF85063A-to-i2c-rtc.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1029-overlays-Fix-cut-and-paste-error-in-README.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1030-media-i2c-imx477-Selection-compliance-fixes.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1032-overlays-mpu6050-Add-addr-parameter.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1033-overlays-Add-missing-addresses-to-ads1015-ads1115.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1034-media-i2c-ov5647-Selection-compliance-fixes.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1035-Add-overlay-for-Seeed-Studio-CAN-BUS-FD-HAT-4034.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1036-overlays-Rebuild-upstream-with-latest-ovmerge.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1037-overlays-give-Seeed-Studio-CAN-BUS-FD-HAT-a-v2-postf.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1038-overlays-Add-overlay-for-Seeed-Studio-CAN-BUS-FD-HAT.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1039-overlays-add-wm8960-soundcard-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1040-overlays-add-spi-override-to-merus-amp-overlay.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1041-overlays-seeed-can-fd-hat-clarify-how-to-identify-HA.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1042-uapi-bcm2835-isp-Add-colour-denoise-configuration.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1043-staging-vc04_services-ISP-Add-colour-denoise-control.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1044-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1045-Adds-the-DT-overlays-to-support-Hifiberry-AMP100.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1046-Enhances-the-Hifiberry-DAC-driver-for-Hifiberry-AMP1.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1047-ARM-dts-Declare-Pi400-and-CM4-have-no-audio-pins.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-1048-Hifiberry-DAC-ADC-Pro-fix-for-the-PLL-when-changing-.patch [new file with mode: 0644]

index c560ff04ad50de7e9de2d6a160f6d5d19c2edb42..e7d384dded901d7548e9fc9894d18b605702f6c9 100644 (file)
@@ -4,21 +4,6 @@ CONFIG_ARCH_32BIT_OFF_T=y
 CONFIG_ARCH_BCM=y
 CONFIG_ARCH_BCM2835=y
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
-CONFIG_ARCH_HAS_BINFMT_FLAT=y
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_ARCH_HAS_KCOV=y
-CONFIG_ARCH_HAS_KEEPINITRD=y
-CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
-CONFIG_ARCH_HAS_PHYS_TO_DMA=y
-CONFIG_ARCH_HAS_SETUP_DMA_OPS=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y
-CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_ARCH_KEEP_MEMBLOCK=y
 CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
@@ -27,23 +12,16 @@ CONFIG_ARCH_MULTI_V6=y
 CONFIG_ARCH_MULTI_V6_V7=y
 CONFIG_ARCH_NR_GPIO=0
 CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_USE_BUILTIN_BSWAP=y
-CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
-CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
-CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
-CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
 CONFIG_ARM=y
 CONFIG_ARM_AMBA=y
-CONFIG_ARM_BCM2835_CPUFREQ=y
+# CONFIG_ARM_BCM2835_CPUFREQ is not set
 CONFIG_ARM_CPU_SUSPEND=y
 CONFIG_ARM_ERRATA_411920=y
 CONFIG_ARM_HAS_SG_CHAIN=y
 CONFIG_ARM_L1_CACHE_SHIFT=5
 CONFIG_ARM_PATCH_PHYS_VIRT=y
-# CONFIG_ARM_RASPBERRYPI_CPUFREQ is not set
+CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
 # CONFIG_ARM_SCMI_PROTOCOL is not set
 CONFIG_ARM_THUMB=y
 CONFIG_ARM_TIMER_SP804=y
@@ -76,7 +54,6 @@ CONFIG_BLK_PM=y
 CONFIG_BLK_SCSI_REQUEST=y
 CONFIG_BRCM_CHAR_DRIVERS=y
 # CONFIG_CACHE_L2X0 is not set
-CONFIG_CC_HAS_KASAN_GENERIC=y
 CONFIG_CLKDEV_LOOKUP=y
 CONFIG_CLKSRC_MMIO=y
 CONFIG_CLK_BCM2835=y
@@ -97,7 +74,8 @@ CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_CONTIG_ALLOC=y
-# CONFIG_CPUFREQ_DT is not set
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
 CONFIG_CPU_32v6=y
 CONFIG_CPU_32v6K=y
 CONFIG_CPU_ABRT_EV6=y
@@ -202,47 +180,13 @@ CONFIG_GENERIC_STRNLEN_USER=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIOLIB_IRQCHIP=y
 # CONFIG_GPIO_BCM_VIRT is not set
+# CONFIG_GPIO_FSM is not set
 CONFIG_GPIO_RASPBERRYPI_EXP=y
 CONFIG_HANDLE_DOMAIN_IRQ=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_HAS_DMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT_MAP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_HAVE_ARCH_PFN_VALID=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_CLK_PREPARE=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_COPY_THREAD_TLS=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
-CONFIG_HAVE_EBPF_JIT=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_HAVE_NET_DSA=y
-CONFIG_HAVE_OPROFILE=y
-CONFIG_HAVE_OPTPROBES=y
-CONFIG_HAVE_PCI=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_PROC_CPU=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_UID16=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
 CONFIG_HW_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_BCM2835=y
@@ -268,6 +212,7 @@ CONFIG_JBD2=y
 CONFIG_KERNEL_GZIP=y
 # CONFIG_KERNEL_XZ is not set
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_ACTPWR=y
 CONFIG_LEDS_TRIGGER_INPUT=y
 CONFIG_LIBFDT=y
 CONFIG_LOCK_DEBUGGING_SUPPORT=y
@@ -332,6 +277,7 @@ CONFIG_PM_CLK=y
 CONFIG_PM_GENERIC_DOMAINS=y
 CONFIG_PM_GENERIC_DOMAINS_OF=y
 CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
+CONFIG_PM_OPP=y
 CONFIG_PM_SLEEP=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_PRINTK_TIME=y
index 017f3eb0adfbfa14a91301857109bf53c0eaf5ff..98ac43375230c29bd4782ad53f7f68f31b6e5fed 100644 (file)
@@ -6,26 +6,6 @@ CONFIG_ARCH_BCM2835=y
 # CONFIG_ARCH_BCM_HR2 is not set
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
 CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_ARCH_HAS_BINFMT_FLAT=y
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_ARCH_HAS_KCOV=y
-CONFIG_ARCH_HAS_KEEPINITRD=y
-CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
-CONFIG_ARCH_HAS_PHYS_TO_DMA=y
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
-CONFIG_ARCH_HAS_SETUP_DMA_OPS=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y
-CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y
-CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y
-CONFIG_ARCH_HAS_TICK_BROADCAST=y
-CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_ARCH_KEEP_MEMBLOCK=y
 CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
@@ -35,14 +15,7 @@ CONFIG_ARCH_MULTI_V7=y
 CONFIG_ARCH_NR_GPIO=0
 CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
 CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_USE_BUILTIN_BSWAP=y
-CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
-CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
-CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
-CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
 CONFIG_ARM=y
 CONFIG_ARM_AMBA=y
 CONFIG_ARM_ARCH_TIMER=y
@@ -96,7 +69,6 @@ CONFIG_BOUNCE=y
 CONFIG_BRCM_CHAR_DRIVERS=y
 CONFIG_BROADCOM_PHY=y
 # CONFIG_CACHE_L2X0 is not set
-CONFIG_CC_HAS_KASAN_GENERIC=y
 CONFIG_CLKDEV_LOOKUP=y
 CONFIG_CLKSRC_MMIO=y
 CONFIG_CLK_BCM2835=y
@@ -204,6 +176,7 @@ CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXTCON=y
 CONFIG_F2FS_FS=y
 CONFIG_FB=y
 CONFIG_FB_BCM2708=y
@@ -254,9 +227,11 @@ CONFIG_GENERIC_SCHED_CLOCK=y
 CONFIG_GENERIC_SMP_IDLE_THREAD=y
 CONFIG_GENERIC_STRNCPY_FROM_USER=y
 CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIOLIB_IRQCHIP=y
 CONFIG_GPIO_BCM_VIRT=y
+# CONFIG_GPIO_FSM is not set
 CONFIG_GPIO_RASPBERRYPI_EXP=y
 CONFIG_HANDLE_DOMAIN_IRQ=y
 CONFIG_HARDEN_BRANCH_PREDICTOR=y
@@ -264,49 +239,7 @@ CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_HAS_DMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT_MAP=y
-CONFIG_HAVE_ARCH_BITREVERSE=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_HAVE_ARCH_PFN_VALID=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARM_ARCH_TIMER=y
-CONFIG_HAVE_ARM_SMCCC=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_CLK_PREPARE=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_COPY_THREAD_TLS=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
-CONFIG_HAVE_EBPF_JIT=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_FAST_GUP=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_IDE=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_HAVE_NET_DSA=y
-CONFIG_HAVE_OPROFILE=y
-CONFIG_HAVE_OPTPROBES=y
-CONFIG_HAVE_PCI=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_PROC_CPU=y
-CONFIG_HAVE_RCU_TABLE_FREE=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
 CONFIG_HAVE_SMP=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_UID16=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
 CONFIG_HIGHMEM=y
 CONFIG_HIGHPTE=y
 CONFIG_HOTPLUG_CPU=y
@@ -335,6 +268,7 @@ CONFIG_IRQ_WORK=y
 CONFIG_JBD2=y
 CONFIG_KEYS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_ACTPWR=y
 CONFIG_LEDS_TRIGGER_INPUT=y
 CONFIG_LIBFDT=y
 CONFIG_LOCK_DEBUGGING_SUPPORT=y
@@ -381,6 +315,7 @@ CONFIG_NEON=y
 CONFIG_NET_FLOW_LIMIT=y
 CONFIG_NLS=y
 CONFIG_NLS_ASCII=y
+CONFIG_NOP_USB_XCEIV=y
 CONFIG_NO_HZ=y
 CONFIG_NO_HZ_COMMON=y
 CONFIG_NO_HZ_IDLE=y
@@ -498,10 +433,12 @@ CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_COMMON=y
 CONFIG_USB_DWCOTG=y
+CONFIG_USB_GADGET=y
 CONFIG_USB_LAN78XX=y
 CONFIG_USB_NET_DRIVERS=y
 CONFIG_USB_NET_SMSC95XX=y
 CONFIG_USB_PCI=y
+CONFIG_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_UAS=y
index a011e2f213419b12f25c17fa7d5e77db33d97832..5aaf021de95c80829bedd7a984cc4f9ff2405a3f 100644 (file)
@@ -3,59 +3,7 @@ CONFIG_64BIT=y
 CONFIG_ARCH_BCM2835=y
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
 CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y
-CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
-CONFIG_ARCH_HAS_KCOV=y
-CONFIG_ARCH_HAS_KEEPINITRD=y
-CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
-CONFIG_ARCH_HAS_PTE_DEVMAP=y
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
-CONFIG_ARCH_HAS_SETUP_DMA_OPS=y
-CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y
-CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y
-CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
-CONFIG_ARCH_HAS_TICK_BROADCAST=y
-CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_INLINE_READ_LOCK=y
-CONFIG_ARCH_INLINE_READ_LOCK_BH=y
-CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_READ_UNLOCK=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_INLINE_SPIN_LOCK=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
-CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_INLINE_WRITE_LOCK=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
 CONFIG_ARCH_KEEP_MEMBLOCK=y
 CONFIG_ARCH_MMAP_RND_BITS=18
 CONFIG_ARCH_MMAP_RND_BITS_MAX=24
@@ -65,20 +13,7 @@ CONFIG_ARCH_PROC_KCORE_TEXT=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
-CONFIG_ARCH_SUPPORTS_INT128=y
-CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
-CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
-CONFIG_ARCH_USE_MEMREMAP_PROT=y
-CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
-CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
-CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
-CONFIG_ARCH_WANT_FRAME_POINTERS=y
-CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
 CONFIG_ARM64=y
 CONFIG_ARM64_4K_PAGES=y
 CONFIG_ARM64_CNP=y
@@ -153,7 +88,6 @@ CONFIG_CAVIUM_ERRATUM_22375=y
 CONFIG_CAVIUM_ERRATUM_23154=y
 CONFIG_CAVIUM_ERRATUM_27456=y
 CONFIG_CAVIUM_TX2_ERRATUM_219=y
-CONFIG_CC_HAS_KASAN_GENERIC=y
 CONFIG_CLKDEV_LOOKUP=y
 CONFIG_CLKSRC_MMIO=y
 CONFIG_CLK_BCM2835=y
@@ -242,11 +176,11 @@ CONFIG_DRM_RCAR_WRITEBACK=y
 CONFIG_DTC=y
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_EDAC_SUPPORT=y
-CONFIG_EFI_EARLYCON=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXTCON=y
 CONFIG_F2FS_FS=y
 CONFIG_FB=y
 CONFIG_FB_BCM2708=y
@@ -305,6 +239,7 @@ CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIOLIB_IRQCHIP=y
 CONFIG_GPIO_BCM_VIRT=y
+# CONFIG_GPIO_FSM is not set
 CONFIG_GPIO_RASPBERRYPI_EXP=y
 CONFIG_HANDLE_DOMAIN_IRQ=y
 CONFIG_HARDEN_BRANCH_PREDICTOR=y
@@ -312,59 +247,6 @@ CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_HAS_DMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT_MAP=y
-CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
-CONFIG_HAVE_ARCH_AUDITSYSCALL=y
-CONFIG_HAVE_ARCH_BITREVERSE=y
-CONFIG_HAVE_ARCH_HUGE_VMAP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
-CONFIG_HAVE_ARCH_KASAN=y
-CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_HAVE_ARCH_PFN_VALID=y
-CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
-CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
-CONFIG_HAVE_ARCH_STACKLEAK=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARCH_VMAP_STACK=y
-CONFIG_HAVE_ARM_SMCCC=y
-CONFIG_HAVE_ASM_MODVERSIONS=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_CLK_PREPARE=y
-CONFIG_HAVE_CMPXCHG_DOUBLE=y
-CONFIG_HAVE_CMPXCHG_LOCAL=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_COPY_THREAD_TLS=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DEBUG_BUGVERBOSE=y
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_EBPF_JIT=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_FAST_GUP=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
-CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_GENERIC_VDSO=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_HAVE_NET_DSA=y
-CONFIG_HAVE_PATA_PLATFORM=y
-CONFIG_HAVE_PCI=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_RCU_TABLE_FREE=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_HOTPLUG_CPU=y
 CONFIG_HW_CONSOLE=y
@@ -379,26 +261,6 @@ CONFIG_I2C_BOARDINFO=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
-CONFIG_INLINE_READ_LOCK=y
-CONFIG_INLINE_READ_LOCK_BH=y
-CONFIG_INLINE_READ_LOCK_IRQ=y
-CONFIG_INLINE_READ_LOCK_IRQSAVE=y
-CONFIG_INLINE_READ_UNLOCK_BH=y
-CONFIG_INLINE_READ_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_SPIN_LOCK=y
-CONFIG_INLINE_SPIN_LOCK_BH=y
-CONFIG_INLINE_SPIN_LOCK_IRQ=y
-CONFIG_INLINE_SPIN_LOCK_IRQSAVE=y
-CONFIG_INLINE_SPIN_TRYLOCK=y
-CONFIG_INLINE_SPIN_TRYLOCK_BH=y
-CONFIG_INLINE_SPIN_UNLOCK_BH=y
-CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_WRITE_LOCK=y
-CONFIG_INLINE_WRITE_LOCK_BH=y
-CONFIG_INLINE_WRITE_LOCK_IRQ=y
-CONFIG_INLINE_WRITE_LOCK_IRQSAVE=y
-CONFIG_INLINE_WRITE_UNLOCK_BH=y
-CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE=y
 CONFIG_INPUT=y
 CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
@@ -412,6 +274,7 @@ CONFIG_IRQ_WORK=y
 CONFIG_JBD2=y
 CONFIG_KEYS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_ACTPWR=y
 CONFIG_LEDS_TRIGGER_INPUT=y
 CONFIG_LIBFDT=y
 CONFIG_LOCK_DEBUGGING_SUPPORT=y
index ee391ff5be551964526cd1aa6315dfc3d3ea66ec..2ba8bfba3d3e5238612b74f95a42d289a5fc2caa 100644 (file)
@@ -3,59 +3,7 @@ CONFIG_64BIT=y
 CONFIG_ARCH_BCM2835=y
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
 CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y
-CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
-CONFIG_ARCH_HAS_KCOV=y
-CONFIG_ARCH_HAS_KEEPINITRD=y
-CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
-CONFIG_ARCH_HAS_PTE_DEVMAP=y
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
-CONFIG_ARCH_HAS_SETUP_DMA_OPS=y
-CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y
-CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y
-CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
-CONFIG_ARCH_HAS_TICK_BROADCAST=y
-CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_INLINE_READ_LOCK=y
-CONFIG_ARCH_INLINE_READ_LOCK_BH=y
-CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_READ_UNLOCK=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_INLINE_SPIN_LOCK=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
-CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
-CONFIG_ARCH_INLINE_WRITE_LOCK=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
-CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
-CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
 CONFIG_ARCH_KEEP_MEMBLOCK=y
 CONFIG_ARCH_MMAP_RND_BITS=18
 CONFIG_ARCH_MMAP_RND_BITS_MAX=24
@@ -65,20 +13,7 @@ CONFIG_ARCH_PROC_KCORE_TEXT=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
-CONFIG_ARCH_SUPPORTS_INT128=y
-CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
-CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
-CONFIG_ARCH_USE_MEMREMAP_PROT=y
-CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
-CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
-CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
-CONFIG_ARCH_WANT_FRAME_POINTERS=y
-CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
 CONFIG_ARM64=y
 CONFIG_ARM64_4K_PAGES=y
 CONFIG_ARM64_CNP=y
@@ -157,7 +92,6 @@ CONFIG_CAVIUM_ERRATUM_22375=y
 CONFIG_CAVIUM_ERRATUM_23154=y
 CONFIG_CAVIUM_ERRATUM_27456=y
 CONFIG_CAVIUM_TX2_ERRATUM_219=y
-CONFIG_CC_HAS_KASAN_GENERIC=y
 CONFIG_CLKDEV_LOOKUP=y
 CONFIG_CLKSRC_MMIO=y
 CONFIG_CLK_BCM2835=y
@@ -247,11 +181,11 @@ CONFIG_DRM_RCAR_WRITEBACK=y
 CONFIG_DTC=y
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_EDAC_SUPPORT=y
-CONFIG_EFI_EARLYCON=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXTCON=y
 CONFIG_F2FS_FS=y
 CONFIG_FB=y
 CONFIG_FB_BCM2708=y
@@ -311,6 +245,7 @@ CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIOLIB_IRQCHIP=y
 CONFIG_GPIO_BCM_VIRT=y
+# CONFIG_GPIO_FSM is not set
 CONFIG_GPIO_RASPBERRYPI_EXP=y
 CONFIG_HANDLE_DOMAIN_IRQ=y
 CONFIG_HARDEN_BRANCH_PREDICTOR=y
@@ -318,59 +253,6 @@ CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_HAS_DMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT_MAP=y
-CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
-CONFIG_HAVE_ARCH_AUDITSYSCALL=y
-CONFIG_HAVE_ARCH_BITREVERSE=y
-CONFIG_HAVE_ARCH_HUGE_VMAP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
-CONFIG_HAVE_ARCH_KASAN=y
-CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_HAVE_ARCH_PFN_VALID=y
-CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
-CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
-CONFIG_HAVE_ARCH_STACKLEAK=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARCH_VMAP_STACK=y
-CONFIG_HAVE_ARM_SMCCC=y
-CONFIG_HAVE_ASM_MODVERSIONS=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_CLK_PREPARE=y
-CONFIG_HAVE_CMPXCHG_DOUBLE=y
-CONFIG_HAVE_CMPXCHG_LOCAL=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_COPY_THREAD_TLS=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DEBUG_BUGVERBOSE=y
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_EBPF_JIT=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_FAST_GUP=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
-CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_GENERIC_VDSO=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_HAVE_NET_DSA=y
-CONFIG_HAVE_PATA_PLATFORM=y
-CONFIG_HAVE_PCI=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_RCU_TABLE_FREE=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_HOTPLUG_CPU=y
 CONFIG_HW_CONSOLE=y
@@ -385,26 +267,6 @@ CONFIG_I2C_BOARDINFO=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
-CONFIG_INLINE_READ_LOCK=y
-CONFIG_INLINE_READ_LOCK_BH=y
-CONFIG_INLINE_READ_LOCK_IRQ=y
-CONFIG_INLINE_READ_LOCK_IRQSAVE=y
-CONFIG_INLINE_READ_UNLOCK_BH=y
-CONFIG_INLINE_READ_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_SPIN_LOCK=y
-CONFIG_INLINE_SPIN_LOCK_BH=y
-CONFIG_INLINE_SPIN_LOCK_IRQ=y
-CONFIG_INLINE_SPIN_LOCK_IRQSAVE=y
-CONFIG_INLINE_SPIN_TRYLOCK=y
-CONFIG_INLINE_SPIN_TRYLOCK_BH=y
-CONFIG_INLINE_SPIN_UNLOCK_BH=y
-CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE=y
-CONFIG_INLINE_WRITE_LOCK=y
-CONFIG_INLINE_WRITE_LOCK_BH=y
-CONFIG_INLINE_WRITE_LOCK_IRQ=y
-CONFIG_INLINE_WRITE_LOCK_IRQSAVE=y
-CONFIG_INLINE_WRITE_UNLOCK_BH=y
-CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE=y
 CONFIG_INPUT=y
 CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
@@ -418,6 +280,7 @@ CONFIG_IRQ_WORK=y
 CONFIG_JBD2=y
 CONFIG_KEYS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_ACTPWR=y
 CONFIG_LEDS_TRIGGER_INPUT=y
 CONFIG_LIBFDT=y
 CONFIG_LOCK_DEBUGGING_SUPPORT=y
@@ -462,6 +325,7 @@ CONFIG_NEED_SG_DMA_LENGTH=y
 CONFIG_NET_FLOW_LIMIT=y
 CONFIG_NLS=y
 CONFIG_NLS_ASCII=y
+CONFIG_NOP_USB_XCEIV=y
 CONFIG_NO_HZ=y
 CONFIG_NO_HZ_COMMON=y
 CONFIG_NO_HZ_IDLE=y
@@ -584,7 +448,9 @@ CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_COMMON=y
 CONFIG_USB_DWCOTG=y
+CONFIG_USB_GADGET=y
 CONFIG_USB_PCI=y
+CONFIG_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_UAS=y
index 8c6f1bf49c011bb8725eae99ed8553fdcd901473..dab31d81324fa027c7b75e779bca2b7ff01c8316 100644 (file)
@@ -133,6 +133,28 @@ endef
 $(eval $(call KernelPackage,sound-soc-allo-boss-dac))
 
 
+define KernelPackage/sound-soc-allo-boss2-dac
+  TITLE:=Support for Allo Boss2 DAC
+  KCONFIG:= \
+    CONFIG_SND_AUDIO_GRAPH_CARD \
+    CONFIG_SND_BCM2708_SOC_ALLO_BOSS2_DAC
+  FILES:= \
+    $(LINUX_DIR)/sound/soc/bcm/snd-soc-allo-boss2-dac.ko
+  AUTOLOAD:=$(call AutoLoad,68,snd-soc-allo-boss2-dac)
+  DEPENDS:= \
+    kmod-sound-soc-bcm2835-i2s \
+    +kmod-i2c-bcm2835 \
+    +kmod-regmap-i2c
+  $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-allo-boss2-dac/description
+  This package contains support for Allo Boss2 DAC
+endef
+
+$(eval $(call KernelPackage,sound-soc-allo-boss2-dac))
+
+
 define KernelPackage/sound-soc-allo-digione
   TITLE:=Support for Allo Piano DigiOne
   KCONFIG:= \
@@ -825,6 +847,28 @@ endef
 $(eval $(call KernelPackage,sound-soc-justboom-digi))
 
 
+define KernelPackage/sound-soc-pifi-40-amp
+  TITLE:=Support for PiFi-40 amp
+  KCONFIG:= \
+    CONFIG_SND_BCM2708_SOC_PIFI_40 \
+    CONFIG_SND_PIFI_40 \
+    CONFIG_SND_SOC_TAS571X
+  FILES:= \
+    $(LINUX_DIR)/sound/soc/bcm/snd-soc-pifi-40.ko \
+    $(LINUX_DIR)/sound/soc/codecs/snd-soc-tas571x.ko
+  AUTOLOAD:=$(call AutoLoad,68,snd-soc-tas571x)
+  DEPENDS:= \
+    kmod-sound-soc-bcm2835-i2s
+  $(call AddDepends/sound)
+endef
+
+define KernelPackage/sound-soc-pifi-40-amp/description
+  This package contains support for PiFi-40 amp
+endef
+
+$(eval $(call KernelPackage,sound-soc-pifi-40-amp))
+
+
 define KernelPackage/sound-soc-pisound
   TITLE:=Support for Blokas Labs PiSound
   KCONFIG:= \
similarity index 95%
rename from target/linux/bcm27xx/patches-5.4/950-0135-spi-spi-bcm2835-Disable-forced-software-CS.patch
rename to target/linux/bcm27xx/patches-5.4/950-0134-spi-spi-bcm2835-Disable-forced-software-CS.patch
index 752464087f7b44f1bc5a18089448ec6ee88feffb..0abe5059c0df04eaafe65db5aea7490ba10600cf 100644 (file)
@@ -13,7 +13,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 
 --- a/drivers/spi/spi-bcm2835.c
 +++ b/drivers/spi/spi-bcm2835.c
-@@ -1278,31 +1278,6 @@ static int bcm2835_spi_setup(struct spi_
+@@ -1230,31 +1230,6 @@ static int bcm2835_spi_setup(struct spi_
                return -EINVAL;
        }
  
diff --git a/target/linux/bcm27xx/patches-5.4/950-0134-spi-spi-bcm2835-Re-enable-HW-CS.patch b/target/linux/bcm27xx/patches-5.4/950-0134-spi-spi-bcm2835-Re-enable-HW-CS.patch
deleted file mode 100644 (file)
index 13dd356..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-From 33b150a792ccde6eded4240dea0e3ec784b07d7c Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 15 Jan 2019 12:39:50 +0000
-Subject: [PATCH] spi: spi-bcm2835: Re-enable HW CS
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/spi/spi-bcm2835.c | 53 +++++++++++++++++++++++++++++++++++++--
- 1 file changed, 51 insertions(+), 2 deletions(-)
-
---- a/drivers/spi/spi-bcm2835.c
-+++ b/drivers/spi/spi-bcm2835.c
-@@ -1169,9 +1169,57 @@ static void bcm2835_spi_handle_err(struc
-       bcm2835_spi_reset_hw(ctlr);
- }
--static int chip_match_name(struct gpio_chip *chip, void *data)
-+static void bcm2835_spi_set_cs(struct spi_device *spi, bool gpio_level)
- {
--      return !strcmp(chip->label, data);
-+      /*
-+       * we can assume that we are "native" as per spi_set_cs
-+       *   calling us ONLY when cs_gpio is not set
-+       * we can also assume that we are CS < 3 as per bcm2835_spi_setup
-+       *   we would not get called because of error handling there.
-+       * the level passed is the electrical level not enabled/disabled
-+       *   so it has to get translated back to enable/disable
-+       *   see spi_set_cs in spi.c for the implementation
-+       */
-+
-+      struct spi_master *master = spi->master;
-+      struct bcm2835_spi *bs = spi_master_get_devdata(master);
-+      u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
-+      bool enable;
-+
-+      /* calculate the enable flag from the passed gpio_level */
-+      enable = (spi->mode & SPI_CS_HIGH) ? gpio_level : !gpio_level;
-+
-+      /* set flags for "reverse" polarity in the registers */
-+      if (spi->mode & SPI_CS_HIGH) {
-+              /* set the correct CS-bits */
-+              cs |= BCM2835_SPI_CS_CSPOL;
-+              cs |= BCM2835_SPI_CS_CSPOL0 << spi->chip_select;
-+      } else {
-+              /* clean the CS-bits */
-+              cs &= ~BCM2835_SPI_CS_CSPOL;
-+              cs &= ~(BCM2835_SPI_CS_CSPOL0 << spi->chip_select);
-+      }
-+
-+      /* select the correct chip_select depending on disabled/enabled */
-+      if (enable) {
-+              /* set cs correctly */
-+              if (spi->mode & SPI_NO_CS) {
-+                      /* use the "undefined" chip-select */
-+                      cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
-+              } else {
-+                      /* set the chip select */
-+                      cs &= ~(BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01);
-+                      cs |= spi->chip_select;
-+              }
-+      } else {
-+              /* disable CSPOL which puts HW-CS into deselected state */
-+              cs &= ~BCM2835_SPI_CS_CSPOL;
-+              /* use the "undefined" chip-select as precaution */
-+              cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
-+      }
-+
-+      /* finally set the calculated flags in SPI_CS */
-+      bcm2835_wr(bs, BCM2835_SPI_CS, cs);
- }
- static int bcm2835_spi_setup(struct spi_device *spi)
-@@ -1276,6 +1324,7 @@ static int bcm2835_spi_probe(struct plat
-       ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
-       ctlr->num_chipselect = BCM2835_SPI_NUM_CS;
-       ctlr->setup = bcm2835_spi_setup;
-+      ctlr->set_cs = bcm2835_spi_set_cs;
-       ctlr->transfer_one = bcm2835_spi_transfer_one;
-       ctlr->handle_err = bcm2835_spi_handle_err;
-       ctlr->prepare_message = bcm2835_spi_prepare_message;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0199-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch b/target/linux/bcm27xx/patches-5.4/950-0199-Bluetooth-Check-key-sizes-only-when-Secure-Simple-Pa.patch
deleted file mode 100644 (file)
index 0de5509..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 3e2981c7e55d75dc93a2f2e9bb6be2b9704c05f5 Mon Sep 17 00:00:00 2001
-From: Marcel Holtmann <marcel@holtmann.org>
-Date: Wed, 22 May 2019 09:05:40 +0200
-Subject: [PATCH] Bluetooth: Check key sizes only when Secure Simple
- Pairing is enabled
-
-The encryption is only mandatory to be enforced when both sides are using
-Secure Simple Pairing and this means the key size check makes only sense
-in that case.
-
-On legacy Bluetooth 2.0 and earlier devices like mice the encryption was
-optional and thus causing an issue if the key size check is not bound to
-using Secure Simple Pairing.
-
-Fixes: d5bb334a8e17 ("Bluetooth: Align minimum encryption key size for LE and BR/EDR connections")
-Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-Cc: stable@vger.kernel.org
----
- net/bluetooth/hci_conn.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/net/bluetooth/hci_conn.c
-+++ b/net/bluetooth/hci_conn.c
-@@ -1302,8 +1302,13 @@ int hci_conn_check_link_mode(struct hci_
-               return 0;
-       }
--      if (hci_conn_ssp_enabled(conn) &&
--          !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
-+      /* If Secure Simple Pairing is not enabled, then legacy connection
-+       * setup is used and no encryption or key sizes can be enforced.
-+       */
-+      if (!hci_conn_ssp_enabled(conn))
-+              return 1;
-+
-+      if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
-               return 0;
-       return 1;
similarity index 95%
rename from target/linux/bcm27xx/patches-5.4/950-0215-spi-bcm2835-enable-shared-interrupt-support.patch
rename to target/linux/bcm27xx/patches-5.4/950-0212-spi-bcm2835-enable-shared-interrupt-support.patch
index 35a4e71245e842d9727680eb8f06cc02654c8637..f82ae7d9f690a12ab18dbe47a89c81b2eebebd78 100644 (file)
@@ -23,7 +23,7 @@ Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
        /* Read as many bytes as possible from FIFO */
        bcm2835_rd_fifo(bs);
        /* Write as many bytes as possible to FIFO */
-@@ -1330,7 +1334,8 @@ static int bcm2835_spi_probe(struct plat
+@@ -1281,7 +1285,8 @@ static int bcm2835_spi_probe(struct plat
        bcm2835_wr(bs, BCM2835_SPI_CS,
                   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
  
diff --git a/target/linux/bcm27xx/patches-5.4/950-0352-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch b/target/linux/bcm27xx/patches-5.4/950-0352-raspberrypi-cpufreq-Only-report-integer-pll-divisor-.patch
deleted file mode 100644 (file)
index 192b13b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From 814af1a008845b61a08111f2f9cf7e66511ab362 Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Fri, 13 Sep 2019 13:45:11 +0100
-Subject: [PATCH] raspberrypi-cpufreq: Only report integer pll divisor
- frequencies
-
----
- drivers/cpufreq/raspberrypi-cpufreq.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/cpufreq/raspberrypi-cpufreq.c
-+++ b/drivers/cpufreq/raspberrypi-cpufreq.c
-@@ -8,6 +8,7 @@
- #include <linux/clk.h>
- #include <linux/cpu.h>
- #include <linux/cpufreq.h>
-+#include <linux/math64.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/pm_opp.h>
-@@ -22,6 +23,7 @@ static int raspberrypi_cpufreq_probe(str
-       unsigned long min, max;
-       unsigned long rate;
-       struct clk *clk;
-+      int div;
-       int ret;
-       cpu_dev = get_cpu_device(0);
-@@ -44,7 +46,10 @@ static int raspberrypi_cpufreq_probe(str
-       max = roundup(clk_round_rate(clk, ULONG_MAX), RASPBERRYPI_FREQ_INTERVAL);
-       clk_put(clk);
--      for (rate = min; rate <= max; rate += RASPBERRYPI_FREQ_INTERVAL) {
-+      for (div = 2; ; div++) {
-+              rate = div_u64((u64)max * 2, div);
-+              if (rate < min)
-+                      break;
-               ret = dev_pm_opp_add(cpu_dev, rate, 0);
-               if (ret)
-                       goto remove_opp;
similarity index 90%
rename from target/linux/bcm27xx/patches-5.4/950-0414-SQUASH-Fix-spi-driver-compiler-warnings.patch
rename to target/linux/bcm27xx/patches-5.4/950-0409-SQUASH-Fix-spi-driver-compiler-warnings.patch
index f233c4aedcf4940a6dd5aeb9eda6073b4eb04ab9..44134391011334baaad42fd19560a37202f25881 100644 (file)
@@ -12,7 +12,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
 
 --- a/drivers/spi/spi-bcm2835.c
 +++ b/drivers/spi/spi-bcm2835.c
-@@ -1230,7 +1230,6 @@ static int bcm2835_spi_setup(struct spi_
+@@ -1182,7 +1182,6 @@ static int bcm2835_spi_setup(struct spi_
  {
        struct spi_controller *ctlr = spi->controller;
        struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0703-overlays-gpio-keys-Avoid-open-drain-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-0703-overlays-gpio-keys-Avoid-open-drain-warnings.patch
deleted file mode 100644 (file)
index 579b3b6..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From ae10c15867d9a5b85eefaf11333bd30473af4b2b Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.com>
-Date: Sat, 2 May 2020 13:43:06 +0100
-Subject: [PATCH] overlays: gpio-keys: Avoid open-drain warnings
-
-The i2c-gpio driver expects to use a GPIO in open-drain mode. Failure
-to configure it in that way causes alarming warnings in the kernel log.
-The BCM283x and BCM2711 GPIO blocks don't support open-drain mode,
-but i2c-gpio works anyway. Silence the warning by declaring that
-open-drain mode has been enabled by other means.
-
-See: https://github.com/raspberrypi/firmware/issues/1381
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.com>
----
- arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
-+++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
-@@ -16,6 +16,8 @@
-                                        &gpio 24 0 /* scl */
-                                       >;
-                               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
-+                              i2c-gpio,sda-open-drain;
-+                              i2c-gpio,scl-open-drain;
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0753-overlays-i2c-rtc-Fix-trickle-resistor-ohms-param.patch b/target/linux/bcm27xx/patches-5.4/950-0753-overlays-i2c-rtc-Fix-trickle-resistor-ohms-param.patch
new file mode 100644 (file)
index 0000000..a702ef7
--- /dev/null
@@ -0,0 +1,26 @@
+From 7871e3600c1190c6cf7968e280bd2fd1ec8bbff2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 29 May 2020 14:41:13 +0100
+Subject: [PATCH] overlays: i2c-rtc: Fix trickle-resistor-ohms param
+
+The abx80x implementation of the trickle-resistor-ohms parameter is
+missing the ":0" indicating that the target is an integer/cell value.
+
+See: https://github.com/raspberrypi/linux/issues/3642
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -229,7 +229,7 @@
+                      <&m41t62>, "reg:0";
+               trickle-diode-type = <&abx80x>,"abracon,tc-diode";
+               trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+-                                      <&abx80x>,"abracon,tc-resistor",
++                                      <&abx80x>,"abracon,tc-resistor:0",
+                                       <&rv3028>,"trickle-resistor-ohms:0";
+               backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
diff --git a/target/linux/bcm27xx/patches-5.4/950-0754-overlays-gpio-shutdown-Add-information-for-SysV-init.patch b/target/linux/bcm27xx/patches-5.4/950-0754-overlays-gpio-shutdown-Add-information-for-SysV-init.patch
new file mode 100644 (file)
index 0000000..ca0fd49
--- /dev/null
@@ -0,0 +1,51 @@
+From 047041db91fabcb768c3e5680645b69fa9528e86 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 30 Apr 2020 19:40:07 +0200
+Subject: [PATCH] overlays: gpio-shutdown: Add information for SysV
+ init / inittab
+
+KeyboardSignal and kb::kbrequest can be used to call /sbin/shutdown
+---
+ arch/arm/boot/dts/overlays/README | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -847,6 +847,7 @@ Params: gpiopin                 GPIO for
+ Name:   gpio-shutdown
+ Info:   Initiates a shutdown when GPIO pin changes. The given GPIO pin
+         is configured as an input key that generates KEY_POWER events.
++
+         This event is handled by systemd-logind by initiating a
+         shutdown. Systemd versions older than 225 need an udev rule
+         enable listening to the input device:
+@@ -855,6 +856,29 @@ Info:   Initiates a shutdown when GPIO p
+                         SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \
+                         ATTRS{keys}=="116", TAG+="power-switch"
++        Alternatively this event can be handled also on systems without
++        systemd, just by traditional SysV init daemon. KEY_POWER event
++        (keycode 116) needs to be mapped to KeyboardSignal on console
++        and then kb::kbrequest inittab action which is triggered by
++        KeyboardSignal from console can be configured to issue system
++        shutdown. Steps for this configuration are:
++
++            Add following lines to the /etc/console-setup/remap.inc file:
++
++                # Key Power as special keypress
++                keycode 116 = KeyboardSignal
++
++            Then add following lines to /etc/inittab file:
++
++                # Action on special keypress (Key Power)
++                kb::kbrequest:/sbin/shutdown -t1 -a -h -P now
++
++            And finally reload configuration by calling following commands:
++
++                # dpkg-reconfigure console-setup
++                # service console-setup reload
++                # init q
++
+         This overlay only handles shutdown. After shutdown, the system
+         can be powered up again by driving GPIO3 low. The default
+         configuration uses GPIO3 with a pullup, so if you connect a
diff --git a/target/linux/bcm27xx/patches-5.4/950-0755-overlays-gpio-shutdown-Add-information-for-Raspberry.patch b/target/linux/bcm27xx/patches-5.4/950-0755-overlays-gpio-shutdown-Add-information-for-Raspberry.patch
new file mode 100644 (file)
index 0000000..5bb6ee2
--- /dev/null
@@ -0,0 +1,62 @@
+From 5f9fcc99c517a517e8d74ce001fc5bc2648f0e59 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Thu, 30 Apr 2020 19:41:10 +0200
+Subject: [PATCH] overlays: gpio-shutdown: Add information for
+ Raspberry Pi 1 Model B rev 1
+
+Raspberry Pi 1 Model B rev 1 uses GPIO1 for power-up instead of GPIO3.
+---
+ arch/arm/boot/dts/overlays/README                    | 10 ++++++++--
+ arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts |  6 ++++--
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -883,9 +883,14 @@ Info:   Initiates a shutdown when GPIO p
+         can be powered up again by driving GPIO3 low. The default
+         configuration uses GPIO3 with a pullup, so if you connect a
+         button between GPIO3 and GND (pin 5 and 6 on the 40-pin header),
+-        you get a shutdown and power-up button.
++        you get a shutdown and power-up button. Please note that
++        Raspberry Pi 1 Model B rev 1 uses GPIO1 instead of GPIO3.
+ Load:   dtoverlay=gpio-shutdown,<param>=<val>
+ Params: gpio_pin                GPIO pin to trigger on (default 3)
++                                For Raspberry Pi 1 Model B rev 1 set this
++                                explicitly to value 1, e.g.:
++
++                                    dtoverlay=gpio-shutdown,gpio_pin=1
+         active_low              When this is 1 (active low), a falling
+                                 edge generates a key down event and a
+@@ -897,7 +902,8 @@ Params: gpio_pin                GPIO pin
+                                 Default is "up".
+                                 Note that the default pin (GPIO3) has an
+-                                external pullup.
++                                external pullup. Same applies for GPIO1
++                                on Raspberry Pi 1 Model B rev 1.
+         debounce                Specify the debounce interval in milliseconds
+                                 (default 100)
+--- a/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-shutdown-overlay.dts
+@@ -4,7 +4,9 @@
+ // This overlay sets up an input device that generates KEY_POWER events
+ // when a given GPIO pin changes. It defaults to using GPIO3, which can
+-// also be used to wake up (start) the Rpi again after shutdown. Since
++// also be used to wake up (start) the Rpi again after shutdown.
++// Raspberry Pi 1 Model B rev 1 can be wake up only by GPIO1 pin, so for
++// these boards change default GPIO pin to 1 via gpio_pin parameter. Since
+ // wakeup is active-low, this defaults to active-low with a pullup
+ // enabled, but all of this can be changed using overlay parameters (but
+ // note that GPIO3 has an external pullup on at least some boards).
+@@ -71,7 +73,7 @@
+               // Allow changing the internal pullup/down state. 0 = none, 1 = pulldown, 2 = pullup
+               // Note that GPIO3 and GPIO2 are the I2c pins and have an external pullup (at least
+-                // on some boards).
++              // on some boards). Same applies for GPIO1 on Raspberry Pi 1 Model B rev 1.
+               gpio_pull = <&pin_state>,"brcm,pull:0";
+               // Allow setting the active_low flag. 0 = active high, 1 = active low
diff --git a/target/linux/bcm27xx/patches-5.4/950-0756-overlays-Add-spi0-overlay-to-support-sc16is752.patch b/target/linux/bcm27xx/patches-5.4/950-0756-overlays-Add-spi0-overlay-to-support-sc16is752.patch
new file mode 100644 (file)
index 0000000..afd760b
--- /dev/null
@@ -0,0 +1,87 @@
+From b2998ffa15aabea3292159ca20973f45ed9cb4b0 Mon Sep 17 00:00:00 2001
+From: bjorn <beikeland@gmail.com>
+Date: Thu, 7 May 2020 05:11:43 +0200
+Subject: [PATCH] overlays: Add spi0 overlay to support sc16is752
+
+Signed-off-by: Bjorn <beikeland@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  8 ++++
+ .../dts/overlays/sc16is752-spi0-overlay.dts   | 44 +++++++++++++++++++
+ 3 files changed, 53 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/sc16is752-spi0-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -143,6 +143,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       rra-digidac1-wm8741-audio.dtbo \
+       sc16is750-i2c.dtbo \
+       sc16is752-i2c.dtbo \
++      sc16is752-spi0.dtbo \
+       sc16is752-spi1.dtbo \
+       sdhost.dtbo \
+       sdio.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2144,6 +2144,14 @@ Params: int_pin                 GPIO use
+         xtal                    On-board crystal frequency (default 14745600)
++Name:   sc16is752-spi0
++Info:   Overlay for the NXP SC16IS752 Dual UART with SPI Interface
++        Enables the chip on SPI0.
++Load:   dtoverlay=sc16is752-spi0,<param>=<val>
++Params: int_pin                 GPIO used for IRQ (default 24)
++        xtal                    On-board crystal frequency (default 14745600)
++
++
+ Name:   sc16is752-spi1
+ Info:   Overlay for the NXP SC16IS752 Dual UART with SPI Interface
+         Enables the chip on SPI1.
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/sc16is752-spi0-overlay.dts
+@@ -0,0 +1,44 @@
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      sc16is752: sc16is752@0 {
++                              compatible = "nxp,sc16is752";
++                              reg = <0>; /* CE0 */
++                              clocks = <&sc16is752_clk>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
++                              #gpio-controller;
++                              #gpio-cells = <2>;
++                              spi-max-frequency = <4000000>;
++
++                              sc16is752_clk: sc16is752_clk {
++                                      compatible = "fixed-clock";
++                                      #clock-cells = <0>;
++                                      clock-frequency = <14745600>;
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      __overrides__ {
++              int_pin = <&sc16is752>,"interrupts:0";
++              xtal = <&sc16is752_clk>, "clock-frequency:0";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0757-overlays-i2c-rtc-gpio-Fix-trickle-resistor-ohms-para.patch b/target/linux/bcm27xx/patches-5.4/950-0757-overlays-i2c-rtc-gpio-Fix-trickle-resistor-ohms-para.patch
new file mode 100644 (file)
index 0000000..6b81afb
--- /dev/null
@@ -0,0 +1,27 @@
+From 00771f36d14f8446ad155ba6fde1f3f608e26642 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 29 May 2020 16:55:12 +0100
+Subject: [PATCH] overlays: i2c-rtc-gpio: Fix trickle-resistor-ohms
+ param
+
+The abx80x implementation of the trickle-resistor-ohms parameter is
+missing the ":0" indicating that the target is an integer/cell value.
+
+See: https://github.com/raspberrypi/linux/issues/3642
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -230,7 +230,7 @@
+               trickle-diode-type = <&abx80x>,"abracon,tc-diode";
+               trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+-                                      <&abx80x>,"abracon,tc-resistor",
++                                      <&abx80x>,"abracon,tc-resistor:0",
+                                       <&rv3028>,"trickle-resistor-ohms:0";
+               backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
diff --git a/target/linux/bcm27xx/patches-5.4/950-0758-media-bcm2835-isp-fix-bytes-per-line-calculations-fo.patch b/target/linux/bcm27xx/patches-5.4/950-0758-media-bcm2835-isp-fix-bytes-per-line-calculations-fo.patch
new file mode 100644 (file)
index 0000000..7f4943f
--- /dev/null
@@ -0,0 +1,80 @@
+From 5b07adb57e04530dc571c2a4a1aeea4b7bc57723 Mon Sep 17 00:00:00 2001
+From: David Plowman <david.plowman@raspberrypi.com>
+Date: Fri, 29 May 2020 14:36:56 +0100
+Subject: [PATCH] media: bcm2835-isp: fix bytes per line calculations
+ for some image formats
+
+The bytes per line numbers calculated by get_bytesperline was not
+matching the equivalent calculation being performed by the VideoCore
+(mostly by the calculate_pitch function there), resulting in failures
+to set the image format with some image width values. This patches up
+the RGB24 and YUYV type formats to match the VideoCore calculation.
+
+Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+---
+ .../vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c       |  6 +++++-
+ .../vc04_services/bcm2835-isp/bcm2835_isp_fmts.h       | 10 +++++-----
+ 2 files changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -676,7 +676,11 @@ struct bcm2835_isp_fmt *get_default_form
+ static inline unsigned int get_bytesperline(int width,
+                                           const struct bcm2835_isp_fmt *fmt)
+ {
+-      return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
++      /* GPU aligns 24bpp images to a multiple of 32 pixels (not bytes). */
++      if (fmt->depth == 24)
++              return ALIGN(width, 32) * 3;
++      else
++              return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
+ }
+ static inline unsigned int get_sizeimage(int bpl, int width, int height,
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_fmts.h
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_fmts.h
+@@ -71,7 +71,7 @@ static const struct bcm2835_isp_fmt supp
+       }, {
+               .fourcc             = V4L2_PIX_FMT_YUYV,
+               .depth              = 16,
+-              .bytesperline_align = 32,
++              .bytesperline_align = 64,
+               .flags              = 0,
+               .mmal_fmt           = MMAL_ENCODING_YUYV,
+               .size_multiplier_x2 = 2,
+@@ -80,7 +80,7 @@ static const struct bcm2835_isp_fmt supp
+       }, {
+               .fourcc             = V4L2_PIX_FMT_UYVY,
+               .depth              = 16,
+-              .bytesperline_align = 32,
++              .bytesperline_align = 64,
+               .flags              = 0,
+               .mmal_fmt           = MMAL_ENCODING_UYVY,
+               .size_multiplier_x2 = 2,
+@@ -89,7 +89,7 @@ static const struct bcm2835_isp_fmt supp
+       }, {
+               .fourcc             = V4L2_PIX_FMT_YVYU,
+               .depth              = 16,
+-              .bytesperline_align = 32,
++              .bytesperline_align = 64,
+               .flags              = 0,
+               .mmal_fmt           = MMAL_ENCODING_YVYU,
+               .size_multiplier_x2 = 2,
+@@ -98,7 +98,7 @@ static const struct bcm2835_isp_fmt supp
+       }, {
+               .fourcc             = V4L2_PIX_FMT_VYUY,
+               .depth              = 16,
+-              .bytesperline_align = 32,
++              .bytesperline_align = 64,
+               .flags              = 0,
+               .mmal_fmt           = MMAL_ENCODING_VYUY,
+               .size_multiplier_x2 = 2,
+@@ -135,7 +135,7 @@ static const struct bcm2835_isp_fmt supp
+       }, {
+               .fourcc             = V4L2_PIX_FMT_ABGR32,
+               .depth              = 32,
+-              .bytesperline_align = 32,
++              .bytesperline_align = 64,
+               .flags              = 0,
+               .mmal_fmt           = MMAL_ENCODING_BGRA,
+               .size_multiplier_x2 = 2,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0759-Add-Micro-Crystal-RV-1805-to-i2c-rtc-overlays.patch b/target/linux/bcm27xx/patches-5.4/950-0759-Add-Micro-Crystal-RV-1805-to-i2c-rtc-overlays.patch
new file mode 100644 (file)
index 0000000..6e9951b
--- /dev/null
@@ -0,0 +1,167 @@
+From 8c16d549cd0b9e9cf890ac3ead5d58d92590140f Mon Sep 17 00:00:00 2001
+From: "Kevin P. Fleming" <kevin+linux@km6g.us>
+Date: Mon, 1 Jun 2020 07:02:00 -0400
+Subject: [PATCH] Add Micro Crystal RV-1805 to i2c-rtc overlays
+
+While the RV-1805 is supported by the rtc-abx80x driver via
+auto-detection, in order for it to be initialized properly
+it must be explcitly selected.
+
+Signed-off-by: Kevin P. Fleming <kevin+linux@km6g.us>
+---
+ arch/arm/boot/dts/overlays/README             | 12 +++++---
+ .../dts/overlays/i2c-rtc-gpio-overlay.dts     | 28 ++++++++++++++++---
+ .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 27 ++++++++++++++++--
+ 3 files changed, 56 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1196,6 +1196,8 @@ Params: abx80x                  Select o
+         pcf8563                 Select the PCF8563 device
++        rv1805                  Select the Micro Crystal RV1805 device
++
+         rv3028                  Select the Micro Crystal RV3028 device
+         addr                    Sets the address for the RTC. Note that the
+@@ -1203,10 +1205,10 @@ Params: abx80x                  Select o
+                                 address.
+         trickle-diode-type      Diode type for trickle charge - "standard" or
+-                                "schottky" (ABx80x only)
++                                "schottky" (ABx80x and RV1805 only)
+         trickle-resistor-ohms   Resistor value for trickle charge (DS1339,
+-                                ABx80x, RV3028)
++                                ABx80x, RV1805, RV3028)
+         wakeup-source           Specify that the RTC can be used as a wakeup
+                                 source
+@@ -1243,6 +1245,8 @@ Params: abx80x                  Select o
+         pcf8563                 Select the PCF8563 device
++        rv1805                  Select the Micro Crystal RV1805 device
++
+         rv3028                  Select the Micro Crystal RV3028 device
+         addr                    Sets the address for the RTC. Note that the
+@@ -1250,10 +1254,10 @@ Params: abx80x                  Select o
+                                 address.
+         trickle-diode-type      Diode type for trickle charge - "standard" or
+-                                "schottky" (ABx80x only)
++                                "schottky" (ABx80x and RV1805 only)
+         trickle-resistor-ohms   Resistor value for trickle charge (DS1339,
+-                                ABx80x, RV3028)
++                                ABx80x, RV1805, RV3028)
+         wakeup-source           Specify that the RTC can be used as a wakeup
+                                 source
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -204,6 +204,23 @@
+               };
+       };
++      fragment@13 {
++              target = <&i2c_gpio>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      rv1805: rv1805@69 {
++                              compatible = "microcrystal,rv1805";
++                              reg = <0x69>;
++                              abracon,tc-diode = "standard";
++                              abracon,tc-resistor = <0>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+1";
+               ds1307 = <0>,"+2";
+@@ -217,6 +234,7 @@
+               m41t62 = <0>,"+10";
+               rv3028 = <0>,"+11";
+               pcf2129 = <0>,"+12";
++              rv1805 = <0>,"+13";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
+@@ -226,12 +244,14 @@
+                      <&mcp7941x>, "reg:0",
+                      <&pcf8523>, "reg:0",
+                      <&pcf8563>, "reg:0",
+-                     <&m41t62>, "reg:0";
+-
+-              trickle-diode-type = <&abx80x>,"abracon,tc-diode";
++                     <&m41t62>, "reg:0",
++                     <&rv1805>, "reg:0";
++              trickle-diode-type = <&abx80x>,"abracon,tc-diode",
++                                   <&rv1805>,"abracon,tc-diode";
+               trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+                                       <&abx80x>,"abracon,tc-resistor:0",
+-                                      <&rv3028>,"trickle-resistor-ohms:0";
++                                      <&rv3028>,"trickle-resistor-ohms:0",
++                                      <&rv1805>,"abracon,tc-resistor:0";
+               backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
+                               <&ds3231>,"wakeup-source?",
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -203,6 +203,23 @@
+               };
+       };
++      fragment@13 {
++              target = <&i2c_arm>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      rv1805: rv1805@69 {
++                              compatible = "microcrystal,rv1805";
++                              reg = <0x69>;
++                              abracon,tc-diode = "standard";
++                              abracon,tc-resistor = <0>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+0";
+               ds1307 = <0>,"+1";
+@@ -217,6 +234,7 @@
+               rv3028 = <0>,"+10";
+               pcf2129 = <0>,"+11";
+               pcf85363 = <0>,"+12";
++              rv1805 = <0>,"+13";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
+@@ -226,11 +244,14 @@
+                      <&mcp7941x>, "reg:0",
+                      <&pcf8523>, "reg:0",
+                      <&pcf8563>, "reg:0",
+-                     <&m41t62>, "reg:0";
+-              trickle-diode-type = <&abx80x>,"abracon,tc-diode";
++                     <&m41t62>, "reg:0",
++                     <&rv1805>, "reg:0";
++              trickle-diode-type = <&abx80x>,"abracon,tc-diode",
++                                   <&rv1805>,"abracon,tc-diode";
+               trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0",
+                                       <&abx80x>,"abracon,tc-resistor:0",
+-                                      <&rv3028>,"trickle-resistor-ohms:0";
++                                      <&rv3028>,"trickle-resistor-ohms:0",
++                                      <&rv1805>,"abracon,tc-resistor:0";
+               backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
+               wakeup-source = <&ds1339>,"wakeup-source?",
+                               <&ds3231>,"wakeup-source?",
diff --git a/target/linux/bcm27xx/patches-5.4/950-0760-vc4-Set-driver_name-for-card.patch b/target/linux/bcm27xx/patches-5.4/950-0760-vc4-Set-driver_name-for-card.patch
new file mode 100644 (file)
index 0000000..0f02d99
--- /dev/null
@@ -0,0 +1,22 @@
+From aff5900c0b389e5ad2b8f2fc67544e769f94cbf4 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Tue, 2 Jun 2020 19:31:49 +0100
+Subject: [PATCH] vc4: Set driver_name for card
+
+Allows use of the same alsa conf file for hdmi1
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -1216,6 +1216,7 @@ static int vc4_hdmi_audio_init(struct vc
+       card->dai_link = dai_link;
+       card->num_links = 1;
+       card->name = vc4_hdmi->variant->id ? "vc4-hdmi1" : "vc4-hdmi";
++      card->driver_name = "vc4-hdmi";
+       card->dev = dev;
+       card->owner = THIS_MODULE;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0761-staging-vchiq_arm-Use-g_dma_dev-for-dma_unmap_sg.patch b/target/linux/bcm27xx/patches-5.4/950-0761-staging-vchiq_arm-Use-g_dma_dev-for-dma_unmap_sg.patch
new file mode 100644 (file)
index 0000000..4af1347
--- /dev/null
@@ -0,0 +1,27 @@
+From fecd0c670aabdbe5bac8fb58be374dd02ea2e8a2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 4 Jun 2020 17:23:36 +0100
+Subject: [PATCH] staging: vchiq_arm: Use g_dma_dev for dma_unmap_sg
+
+Commit "staging: vchiq_arm: Clean up 40-bit DMA support" failed to
+change one of the calls to dma_unmap_sg to pass in g_dma_dev (rather
+than g_dev). Correct that oversight.
+
+See: https://github.com/raspberrypi/linux/issues/3647
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ .../staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c  | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -641,7 +641,7 @@ free_pagelist(struct vchiq_pagelist_info
+        * NOTE: dma_unmap_sg must be called before the
+        * cpu can touch any of the data/pages.
+        */
+-      dma_unmap_sg(g_dev, pagelistinfo->scatterlist,
++      dma_unmap_sg(g_dma_dev, pagelistinfo->scatterlist,
+                    pagelistinfo->num_pages, pagelistinfo->dma_dir);
+       pagelistinfo->scatterlist_mapped = 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0762-vc4-cec-Restore-cec-physical-address-on-reconnect.patch b/target/linux/bcm27xx/patches-5.4/950-0762-vc4-cec-Restore-cec-physical-address-on-reconnect.patch
new file mode 100644 (file)
index 0000000..d42f61d
--- /dev/null
@@ -0,0 +1,56 @@
+From 7776a876ce7a6eeda164aebacc965116821d3095 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Wed, 3 Jun 2020 12:20:19 +0100
+Subject: [PATCH] vc4: cec: Restore cec physical address on reconnect
+
+Currently we call cec_phys_addr_invalidate on a hotplug deassert.
+That may be due to a TV power cycling, or an AVR being switched
+on (and switching edid). This makes CEC unusable.
+
+Set it back up again on the hotplug assert.
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -113,20 +113,29 @@ static enum drm_connector_status
+ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
+ {
+       struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
++      bool connected = false;
+       if (vc4_hdmi->hpd_gpio) {
+               if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
+                   vc4_hdmi->hpd_active_low)
+-                      return connector_status_connected;
+-              cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
+-              return connector_status_disconnected;
+-      }
+-
+-      if (drm_probe_ddc(vc4_hdmi->ddc))
+-              return connector_status_connected;
+-
++                      connected = true;
++      } else if (drm_probe_ddc(vc4_hdmi->ddc))
++              connected = true;
+       if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
++              connected = true;
++      if (connected) {
++              if (connector->status != connector_status_connected) {
++                      struct edid *edid = drm_get_edid(connector, vc4_hdmi->ddc);
++
++                      if (edid) {
++                              cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
++                              vc4_hdmi->encoder.hdmi_monitor = drm_detect_hdmi_monitor(edid);
++                              drm_connector_update_edid_property(connector, edid);
++                              kfree(edid);
++                      }
++              }
+               return connector_status_connected;
++      }
+       cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
+       return connector_status_disconnected;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0763-snd_bcm2835-disable-HDMI-audio-when-vc4-is-used-3640.patch b/target/linux/bcm27xx/patches-5.4/950-0763-snd_bcm2835-disable-HDMI-audio-when-vc4-is-used-3640.patch
new file mode 100644 (file)
index 0000000..ed45410
--- /dev/null
@@ -0,0 +1,92 @@
+From 744543757bef8621f7791e28ecb894b2627cb449 Mon Sep 17 00:00:00 2001
+From: Hristo Venev <hristo@venev.name>
+Date: Fri, 5 Jun 2020 09:22:49 +0000
+Subject: [PATCH] snd_bcm2835: disable HDMI audio when vc4 is used
+ (#3640)
+
+Things don't work too well when both the vc4 driver and the firmware
+driver are trying to control the same audio output:
+
+[  763.569406] bcm2835_audio bcm2835_audio: vchi message timeout, msg=5
+
+Hence, when the vc4 HDMI driver is used, let it control audio. This is done
+by introducing a new device tree property to the audio node, and
+extending the vc4-kms-v3d overlays to set it appropriately.
+
+Signed-off-by: Hristo Venev <hristo@venev.name>
+---
+ arch/arm/boot/dts/overlays/README                      |  2 ++
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts     | 10 +++++++++-
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts |  8 ++++++++
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c  |  4 +++-
+ 4 files changed, 22 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2745,6 +2745,7 @@ Params: cma-256                 CMA is 2
+         cma-size                CMA size in bytes, 4MB aligned
+         cma-default             Use upstream's default value
+         audio                   Enable or disable audio over HDMI (default "on")
++        noaudio                 Disable all HDMI audio (default "off")
+ Name:   vc4-kms-v3d-pi4
+@@ -2761,6 +2762,7 @@ Params: cma-256                 CMA is 2
+                                 "on")
+         audio1                  Enable or disable audio over HDMI1 (default
+                                 "on")
++        noaudio                 Disable all HDMI audio (default "off")
+ Name:   vga666
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts
+@@ -108,7 +108,15 @@
+               };
+       };
++      fragment@14 {
++              target = <&audio>;
++              __overlay__  {
++                  brcm,disable-hdmi;
++              };
++      };
++
+       __overrides__ {
+-              audio   = <0>,"!13";
++              audio   = <0>,"!13", <0>,"=14";
++              noaudio = <0>,"=13", <0>,"!14";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts
+@@ -138,8 +138,16 @@
+               };
+       };
++      fragment@19 {
++              target = <&audio>;
++              __overlay__  {
++                  brcm,disable-hdmi;
++              };
++      };
++
+       __overrides__ {
+               audio   = <0>,"!17";
+               audio1   = <0>,"!18";
++              noaudio = <0>,"=17", <0>,"=18", <0>,"!19";
+       };
+ };
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -381,7 +381,9 @@ static int snd_bcm2835_alsa_probe(struct
+       }
+       if (!enable_compat_alsa) {
+-              set_hdmi_enables(dev);
++              if (!of_property_read_bool(dev->of_node, "brcm,disable-hdmi"))
++                      set_hdmi_enables(dev);
++
+               // In this mode, always enable analog output
+               enable_headphones = true;
+       } else {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0764-overlays-i2c-gpio-Avoid-open-drain-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-0764-overlays-i2c-gpio-Avoid-open-drain-warnings.patch
new file mode 100644 (file)
index 0000000..9b6cb1d
--- /dev/null
@@ -0,0 +1,93 @@
+From 11f89a12530471a2b25c71416e106eaa014818c0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 5 Jun 2020 16:07:07 +0100
+Subject: [PATCH] overlays: i2c-gpio: Avoid open-drain warnings
+
+The i2c-gpio driver expects to use a GPIO in open-drain mode. Failure
+to configure it in that way causes alarming warnings in the kernel log.
+The BCM283x and BCM2711 GPIO blocks don't support open-drain mode, but
+gpiolib can emulate it in software if configured correctly.
+
+Silence the warning by declaring the GPIOs as requiring open-drain
+mode, trusting gpiolib to manage the emulation. The previous
+incarnation of this patch took the other approach of telling the
+i2c-gpio driver that the GPIOs were configured for open-drain, but
+this had the effect of disabling the emulation. In some cases this
+appears to work, but examining the waveforms as analogue voltages
+shows contention, the success or failure depending on drive strengths.
+
+See: https://github.com/raspberrypi/firmware/issues/1381
+See: https://github.com/raspberrypi/firmware/issues/1401
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/balena-fin-overlay.dts   | 5 ++++-
+ arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts     | 6 ++++--
+ arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts | 6 ++++--
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
++++ b/arch/arm/boot/dts/overlays/balena-fin-overlay.dts
+@@ -1,6 +1,8 @@
+ /dts-v1/;
+ /plugin/;
++#include <dt-bindings/gpio/gpio.h>
++
+ /{
+       compatible = "brcm,bcm2835";
+@@ -48,7 +50,8 @@
+                       i2c_soft: i2c@0 {
+                               compatible = "i2c-gpio";
+-                              gpios = <&gpio 43 0 /* sda */ &gpio 42 0 /* scl */>;
++                              gpios = <&gpio 43 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* sda */
++                                       &gpio 42 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* scl */>;
+                               i2c-gpio,delay-us = <5>;
+                               i2c-gpio,scl-open-drain;
+                               i2c-gpio,sda-open-drain;
+--- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts
+@@ -2,6 +2,8 @@
+ /dts-v1/;
+ /plugin/;
++#include <dt-bindings/gpio/gpio.h>
++
+ / {
+       compatible = "brcm,bcm2835";
+@@ -12,8 +14,8 @@
+                       i2c_gpio: i2c@0 {
+                               reg = <0xffffffff>;
+                               compatible = "i2c-gpio";
+-                              gpios = <&gpio 23 0 /* sda */
+-                                       &gpio 24 0 /* scl */
++                              gpios = <&gpio 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* sda */
++                                       &gpio 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* scl */
+                                       >;
+                               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+                               #address-cells = <1>;
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-gpio-overlay.dts
+@@ -3,6 +3,8 @@
+ /dts-v1/;
+ /plugin/;
++#include <dt-bindings/gpio/gpio.h>
++
+ / {
+       compatible = "brcm,bcm2835";
+@@ -11,8 +13,8 @@
+               __overlay__ {
+                       i2c_gpio: i2c-gpio-rtc@0 {
+                               compatible = "i2c-gpio";
+-                              gpios = <&gpio 23 0 /* sda */
+-                                       &gpio 24 0 /* scl */
++                              gpios = <&gpio 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* sda */
++                                       &gpio 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* scl */
+                                       >;
+                               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+                               #address-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0765-overlays-Update-upstream-overlays-after-vc4-kms-v3d-.patch b/target/linux/bcm27xx/patches-5.4/950-0765-overlays-Update-upstream-overlays-after-vc4-kms-v3d-.patch
new file mode 100644 (file)
index 0000000..dd5f2ee
--- /dev/null
@@ -0,0 +1,42 @@
+From 964d9575e0a9849f197edaa243e9f2268d5ab44e Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 5 Jun 2020 16:18:52 +0100
+Subject: [PATCH] overlays: Update upstream overlays after
+ vc4-kms-v3d change
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/upstream-overlay.dts     | 6 ++++++
+ arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts | 6 ++++++
+ 2 files changed, 12 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -92,6 +92,12 @@
+               };
+       };
+       fragment@14 {
++              target = <&audio>;
++              __overlay__ {
++                      brcm,disable-hdmi;
++              };
++      };
++      fragment@15 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+--- a/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
+@@ -122,6 +122,12 @@
+               };
+       };
+       fragment@19 {
++              target = <&audio>;
++              __overlay__ {
++                      brcm,disable-hdmi;
++              };
++      };
++      fragment@20 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch b/target/linux/bcm27xx/patches-5.4/950-0766-w1_therm-adding-code-comments-and-code-reordering.patch
new file mode 100644 (file)
index 0000000..5db0512
--- /dev/null
@@ -0,0 +1,580 @@
+From 7c49e87acd0412ff1fb2490c4ac6fcb5471afd9b Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:35:35 +0200
+Subject: [PATCH] w1_therm: adding code comments and code reordering
+
+commit 92b8d2724464bc1d2e735a84c0da5741dce33485 upstream.
+
+Adding code comments to split code in dedicated parts. After the global
+declarations (defines, macros and function declarations), code is organized
+as follow :
+ - Device and family dependent structures and functions
+ - Interfaces functions
+ - Helpers functions
+ - Hardware functions
+ - Sysfs interface functions
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203535.409599-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_therm.c | 427 +++++++++++++++++++++--------------
+ 1 file changed, 259 insertions(+), 168 deletions(-)
+
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -25,7 +25,8 @@
+ #define W1_THERM_DS1825               0x3B
+ #define W1_THERM_DS28EA00     0x42
+-/* Allow the strong pullup to be disabled, but default to enabled.
++/*
++ * Allow the strong pullup to be disabled, but default to enabled.
+  * If it was disabled a parasite powered device might not get the require
+  * current to do a temperature conversion.  If it is enabled parasite powered
+  * devices have a better chance of getting the current required.
+@@ -41,42 +42,55 @@
+ static int w1_strong_pullup = 1;
+ module_param_named(strong_pullup, w1_strong_pullup, int, 0);
++/* Helpers Macros */
++
++/* return the address of the refcnt in the family data */
++#define THERM_REFCNT(family_data) \
++      (&((struct w1_therm_family_data *)family_data)->refcnt)
++
++/* Structs definition */
++
++/**
++ * struct w1_therm_family_converter - bind device specific functions
++ * @broken: flag for non-registred families
++ * @reserved: not used here
++ * @f: pointer to the device binding structure
++ * @convert: pointer to the device conversion function
++ * @precision: pointer to the device precision function
++ * @eeprom: pointer to eeprom function
++ */
++struct w1_therm_family_converter {
++      u8              broken;
++      u16             reserved;
++      struct w1_family        *f;
++      int             (*convert)(u8 rom[9]);
++      int             (*precision)(struct device *device, int val);
++      int             (*eeprom)(struct device *device);
++};
++
++/**
++ * struct w1_therm_family_data - device data
++ * @rom: ROM device id (64bit Lasered ROM code + 1 CRC byte)
++ * @refcnt: ref count
++ */
+ struct w1_therm_family_data {
+       uint8_t rom[9];
+       atomic_t refcnt;
+ };
++/**
++ * struct therm_info - store temperature reading
++ * @rom: read device data (8 data bytes + 1 CRC byte)
++ * @crc: computed crc from rom
++ * @verdict: 1 crc checked, 0 crc not matching
++ */
+ struct therm_info {
+       u8 rom[9];
+       u8 crc;
+       u8 verdict;
+ };
+-/* return the address of the refcnt in the family data */
+-#define THERM_REFCNT(family_data) \
+-      (&((struct w1_therm_family_data *)family_data)->refcnt)
+-
+-static int w1_therm_add_slave(struct w1_slave *sl)
+-{
+-      sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
+-              GFP_KERNEL);
+-      if (!sl->family_data)
+-              return -ENOMEM;
+-      atomic_set(THERM_REFCNT(sl->family_data), 1);
+-      return 0;
+-}
+-
+-static void w1_therm_remove_slave(struct w1_slave *sl)
+-{
+-      int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
+-
+-      while (refcnt) {
+-              msleep(1000);
+-              refcnt = atomic_read(THERM_REFCNT(sl->family_data));
+-      }
+-      kfree(sl->family_data);
+-      sl->family_data = NULL;
+-}
++/* Sysfs interface declaration */
+ static ssize_t w1_slave_show(struct device *device,
+       struct device_attribute *attr, char *buf);
+@@ -87,9 +101,35 @@ static ssize_t w1_slave_store(struct dev
+ static ssize_t w1_seq_show(struct device *device,
+       struct device_attribute *attr, char *buf);
++/* Attributes declarations */
++
+ static DEVICE_ATTR_RW(w1_slave);
+ static DEVICE_ATTR_RO(w1_seq);
++/* Interface Functions declaration */
++
++/**
++ * w1_therm_add_slave() - Called when a new slave is discovered
++ * @sl: slave just discovered by the master.
++ *
++ * Called by the master when the slave is discovered on the bus. Used to
++ * initialize slave state before the beginning of any communication.
++ *
++ * Return: 0 - If success, negative kernel code otherwise
++ */
++static int w1_therm_add_slave(struct w1_slave *sl);
++
++/**
++ * w1_therm_remove_slave() - Called when a slave is removed
++ * @sl: slave to be removed.
++ *
++ * Called by the master when the slave is considered not to be on the bus
++ * anymore. Used to free memory.
++ */
++static void w1_therm_remove_slave(struct w1_slave *sl);
++
++/* Family attributes */
++
+ static struct attribute *w1_therm_attrs[] = {
+       &dev_attr_w1_slave.attr,
+       NULL,
+@@ -101,6 +141,8 @@ static struct attribute *w1_ds28ea00_att
+       NULL,
+ };
++/* Attribute groups */
++
+ ATTRIBUTE_GROUPS(w1_therm);
+ ATTRIBUTE_GROUPS(w1_ds28ea00);
+@@ -154,6 +196,8 @@ static const struct hwmon_chip_info w1_c
+ #define W1_CHIPINFO   NULL
+ #endif
++/* Family operations */
++
+ static struct w1_family_ops w1_therm_fops = {
+       .add_slave      = w1_therm_add_slave,
+       .remove_slave   = w1_therm_remove_slave,
+@@ -168,6 +212,8 @@ static struct w1_family_ops w1_ds28ea00_
+       .chip_info      = W1_CHIPINFO,
+ };
++/* Family binding operations struct */
++
+ static struct w1_family w1_therm_family_DS18S20 = {
+       .fid = W1_THERM_DS18S20,
+       .fops = &w1_therm_fops,
+@@ -193,138 +239,18 @@ static struct w1_family w1_therm_family_
+       .fops = &w1_therm_fops,
+ };
+-struct w1_therm_family_converter {
+-      u8                      broken;
+-      u16                     reserved;
+-      struct w1_family        *f;
+-      int                     (*convert)(u8 rom[9]);
+-      int                     (*precision)(struct device *device, int val);
+-      int                     (*eeprom)(struct device *device);
+-};
++/* Device dependent func */
+ /* write configuration to eeprom */
+ static inline int w1_therm_eeprom(struct device *device);
+-/* Set precision for conversion */
+-static inline int w1_DS18B20_precision(struct device *device, int val);
+-static inline int w1_DS18S20_precision(struct device *device, int val);
+-
+-/* The return value is millidegrees Centigrade. */
+-static inline int w1_DS18B20_convert_temp(u8 rom[9]);
+-static inline int w1_DS18S20_convert_temp(u8 rom[9]);
+-
+-static struct w1_therm_family_converter w1_therm_families[] = {
+-      {
+-              .f              = &w1_therm_family_DS18S20,
+-              .convert        = w1_DS18S20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
+-              .eeprom         = w1_therm_eeprom
+-      },
+-      {
+-              .f              = &w1_therm_family_DS1822,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
+-              .eeprom         = w1_therm_eeprom
+-      },
+-      {
+-              .f              = &w1_therm_family_DS18B20,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18B20_precision,
+-              .eeprom         = w1_therm_eeprom
+-      },
+-      {
+-              .f              = &w1_therm_family_DS28EA00,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
+-              .eeprom         = w1_therm_eeprom
+-      },
+-      {
+-              .f              = &w1_therm_family_DS1825,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
+-              .eeprom         = w1_therm_eeprom
+-      }
+-};
+-
+-static inline int w1_therm_eeprom(struct device *device)
+-{
+-      struct w1_slave *sl = dev_to_w1_slave(device);
+-      struct w1_master *dev = sl->master;
+-      u8 rom[9], external_power;
+-      int ret, max_trying = 10;
+-      u8 *family_data = sl->family_data;
+-
+-      if (!sl->family_data) {
+-              ret = -ENODEV;
+-              goto error;
+-      }
+-
+-      /* prevent the slave from going away in sleep */
+-      atomic_inc(THERM_REFCNT(family_data));
+-
+-      ret = mutex_lock_interruptible(&dev->bus_mutex);
+-      if (ret != 0)
+-              goto dec_refcnt;
+-
+-      memset(rom, 0, sizeof(rom));
+-
+-      while (max_trying--) {
+-              if (!w1_reset_select_slave(sl)) {
+-                      unsigned int tm = 10;
+-                      unsigned long sleep_rem;
+-
+-                      /* check if in parasite mode */
+-                      w1_write_8(dev, W1_READ_PSUPPLY);
+-                      external_power = w1_read_8(dev);
+-
+-                      if (w1_reset_select_slave(sl))
+-                              continue;
+-
+-                      /* 10ms strong pullup/delay after the copy command */
+-                      if (w1_strong_pullup == 2 ||
+-                          (!external_power && w1_strong_pullup))
+-                              w1_next_pullup(dev, tm);
+-
+-                      w1_write_8(dev, W1_COPY_SCRATCHPAD);
+-
+-                      if (external_power) {
+-                              mutex_unlock(&dev->bus_mutex);
+-
+-                              sleep_rem = msleep_interruptible(tm);
+-                              if (sleep_rem != 0) {
+-                                      ret = -EINTR;
+-                                      goto dec_refcnt;
+-                              }
+-
+-                              ret = mutex_lock_interruptible(&dev->bus_mutex);
+-                              if (ret != 0)
+-                                      goto dec_refcnt;
+-                      } else if (!w1_strong_pullup) {
+-                              sleep_rem = msleep_interruptible(tm);
+-                              if (sleep_rem != 0) {
+-                                      ret = -EINTR;
+-                                      goto mt_unlock;
+-                              }
+-                      }
+-
+-                      break;
+-              }
+-      }
+-
+-mt_unlock:
+-      mutex_unlock(&dev->bus_mutex);
+-dec_refcnt:
+-      atomic_dec(THERM_REFCNT(family_data));
+-error:
+-      return ret;
+-}
+-
+ /* DS18S20 does not feature configuration register */
+ static inline int w1_DS18S20_precision(struct device *device, int val)
+ {
+       return 0;
+ }
++/* Set precision for conversion */
+ static inline int w1_DS18B20_precision(struct device *device, int val)
+ {
+       struct w1_slave *sl = dev_to_w1_slave(device);
+@@ -407,6 +333,14 @@ error:
+       return ret;
+ }
++/**
++ * w1_DS18B20_convert_temp() - temperature computation for DS18B20
++ * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
++ *
++ * Can be called for any DS18B20 compliant device.
++ *
++ * Return: value in millidegrees Celsius.
++ */
+ static inline int w1_DS18B20_convert_temp(u8 rom[9])
+ {
+       s16 t = le16_to_cpup((__le16 *)rom);
+@@ -414,6 +348,14 @@ static inline int w1_DS18B20_convert_tem
+       return t*1000/16;
+ }
++/**
++ * w1_DS18S20_convert_temp() - temperature computation for DS18S20
++ * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
++ *
++ * Can be called for any DS18S20 compliant device.
++ *
++ * Return: value in millidegrees Celsius.
++ */
+ static inline int w1_DS18S20_convert_temp(u8 rom[9])
+ {
+       int t, h;
+@@ -434,6 +376,53 @@ static inline int w1_DS18S20_convert_tem
+       return t;
+ }
++/* Device capability description */
++
++static struct w1_therm_family_converter w1_therm_families[] = {
++      {
++              .f              = &w1_therm_family_DS18S20,
++              .convert        = w1_DS18S20_convert_temp,
++              .precision      = w1_DS18S20_precision,
++              .eeprom         = w1_therm_eeprom
++      },
++      {
++              .f              = &w1_therm_family_DS1822,
++              .convert        = w1_DS18B20_convert_temp,
++              .precision      = w1_DS18S20_precision,
++              .eeprom         = w1_therm_eeprom
++      },
++      {
++              .f              = &w1_therm_family_DS18B20,
++              .convert        = w1_DS18B20_convert_temp,
++              .precision      = w1_DS18B20_precision,
++              .eeprom         = w1_therm_eeprom
++      },
++      {
++              .f              = &w1_therm_family_DS28EA00,
++              .convert        = w1_DS18B20_convert_temp,
++              .precision      = w1_DS18S20_precision,
++              .eeprom         = w1_therm_eeprom
++      },
++      {
++              .f              = &w1_therm_family_DS1825,
++              .convert        = w1_DS18B20_convert_temp,
++              .precision      = w1_DS18S20_precision,
++              .eeprom         = w1_therm_eeprom
++      }
++};
++
++/* Helpers Functions */
++
++/**
++ * w1_convert_temp() - temperature conversion binding function
++ * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
++ * @fid: device family id
++ *
++ * The function call the temperature computation function according to
++ * device family.
++ *
++ * Return: value in millidegrees Celsius.
++ */
+ static inline int w1_convert_temp(u8 rom[9], u8 fid)
+ {
+       int i;
+@@ -445,31 +434,32 @@ static inline int w1_convert_temp(u8 rom
+       return 0;
+ }
+-static ssize_t w1_slave_store(struct device *device,
+-                            struct device_attribute *attr, const char *buf,
+-                            size_t size)
++/* Interface Functions */
++
++static int w1_therm_add_slave(struct w1_slave *sl)
+ {
+-      int val, ret;
+-      struct w1_slave *sl = dev_to_w1_slave(device);
+-      int i;
++      sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
++              GFP_KERNEL);
++      if (!sl->family_data)
++              return -ENOMEM;
++      atomic_set(THERM_REFCNT(sl->family_data), 1);
++      return 0;
++}
+-      ret = kstrtoint(buf, 0, &val);
+-      if (ret)
+-              return ret;
++static void w1_therm_remove_slave(struct w1_slave *sl)
++{
++      int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
+-      for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
+-              if (w1_therm_families[i].f->fid == sl->family->fid) {
+-                      /* zero value indicates to write current configuration to eeprom */
+-                      if (val == 0)
+-                              ret = w1_therm_families[i].eeprom(device);
+-                      else
+-                              ret = w1_therm_families[i].precision(device, val);
+-                      break;
+-              }
++      while (refcnt) {
++              msleep(1000);
++              refcnt = atomic_read(THERM_REFCNT(sl->family_data));
+       }
+-      return ret ? : size;
++      kfree(sl->family_data);
++      sl->family_data = NULL;
+ }
++/* Hardware Functions */
++
+ static ssize_t read_therm(struct device *device,
+                         struct w1_slave *sl, struct therm_info *info)
+ {
+@@ -564,6 +554,81 @@ error:
+       return ret;
+ }
++static inline int w1_therm_eeprom(struct device *device)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      struct w1_master *dev = sl->master;
++      u8 rom[9], external_power;
++      int ret, max_trying = 10;
++      u8 *family_data = sl->family_data;
++
++      if (!sl->family_data) {
++              ret = -ENODEV;
++              goto error;
++      }
++
++      /* prevent the slave from going away in sleep */
++      atomic_inc(THERM_REFCNT(family_data));
++
++      ret = mutex_lock_interruptible(&dev->bus_mutex);
++      if (ret != 0)
++              goto dec_refcnt;
++
++      memset(rom, 0, sizeof(rom));
++
++      while (max_trying--) {
++              if (!w1_reset_select_slave(sl)) {
++                      unsigned int tm = 10;
++                      unsigned long sleep_rem;
++
++                      /* check if in parasite mode */
++                      w1_write_8(dev, W1_READ_PSUPPLY);
++                      external_power = w1_read_8(dev);
++
++                      if (w1_reset_select_slave(sl))
++                              continue;
++
++                      /* 10ms strong pullup/delay after the copy command */
++                      if (w1_strong_pullup == 2 ||
++                          (!external_power && w1_strong_pullup))
++                              w1_next_pullup(dev, tm);
++
++                      w1_write_8(dev, W1_COPY_SCRATCHPAD);
++
++                      if (external_power) {
++                              mutex_unlock(&dev->bus_mutex);
++
++                              sleep_rem = msleep_interruptible(tm);
++                              if (sleep_rem != 0) {
++                                      ret = -EINTR;
++                                      goto dec_refcnt;
++                              }
++
++                              ret = mutex_lock_interruptible(&dev->bus_mutex);
++                              if (ret != 0)
++                                      goto dec_refcnt;
++                      } else if (!w1_strong_pullup) {
++                              sleep_rem = msleep_interruptible(tm);
++                              if (sleep_rem != 0) {
++                                      ret = -EINTR;
++                                      goto mt_unlock;
++                              }
++                      }
++
++                      break;
++              }
++      }
++
++mt_unlock:
++      mutex_unlock(&dev->bus_mutex);
++dec_refcnt:
++      atomic_dec(THERM_REFCNT(family_data));
++error:
++      return ret;
++}
++
++/* Sysfs Interface definition */
++
+ static ssize_t w1_slave_show(struct device *device,
+                            struct device_attribute *attr, char *buf)
+ {
+@@ -597,6 +662,32 @@ static ssize_t w1_slave_show(struct devi
+       return ret;
+ }
++static ssize_t w1_slave_store(struct device *device,
++                            struct device_attribute *attr, const char *buf,
++                            size_t size)
++{
++      int val, ret;
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      int i;
++
++      ret = kstrtoint(buf, 0, &val);
++      if (ret)
++              return ret;
++
++      for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
++              if (w1_therm_families[i].f->fid == sl->family->fid) {
++      /* zero value indicates to write current configuration to eeprom */
++                      if (val == 0)
++                              ret = w1_therm_families[i].eeprom(device);
++                      else
++                              ret = w1_therm_families[i].precision(device,
++                                                                      val);
++                      break;
++              }
++      }
++      return ret ? : size;
++}
++
+ #if IS_REACHABLE(CONFIG_HWMON)
+ static int w1_read_temp(struct device *device, u32 attr, int channel,
+                       long *val)
+@@ -666,7 +757,7 @@ static ssize_t w1_seq_show(struct device
+       if (ack != W1_42_SUCCESS_CONFIRM_BYTE)
+               goto error;
+-      /* In case the bus fails to send 0xFF, limit*/
++      /* In case the bus fails to send 0xFF, limit */
+       for (i = 0; i <= 64; i++) {
+               if (w1_reset_bus(sl->master))
+                       goto error;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch b/target/linux/bcm27xx/patches-5.4/950-0767-w1_therm-fix-reset_select_slave-during-discovery.patch
new file mode 100644 (file)
index 0000000..9881f81
--- /dev/null
@@ -0,0 +1,149 @@
+From dfc9fd0060f9103ca1f9335d529401ee8a105737 Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:36:10 +0200
+Subject: [PATCH] w1_therm: fix reset_select_slave during discovery
+
+commit c8ad65f6fbfdcb9b620674ef456020eef2bfeb36 upstream.
+
+Fix reset_select_slave issue during devices discovery by the master on
+bus. The w1_reset_select_slave() from w1_io.c, which was previously used,
+assume that if the slave count is 1 there is only one slave attached on
+the bus. This is not always true. For example when discovering devices,
+when the first device is discover by the bus master, its slave count is
+1, but some other slaves may be on the bus.
+
+In that case instead of adressing command to the attached slave the
+master throw a SKIP ROM command so that all slaves attached on the bus
+will answer simultenaously causing data collision.
+
+A dedicated reset_select_slave() function is implemented here,
+it always perform an adressing to each slave using the MATCH ROM
+command.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203610.409975-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_therm.c | 48 ++++++++++++++++++++++++++++++------
+ 1 file changed, 41 insertions(+), 7 deletions(-)
+
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -16,6 +16,7 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/hwmon.h>
++#include <linux/string.h>
+ #include <linux/w1.h>
+@@ -90,6 +91,24 @@ struct therm_info {
+       u8 verdict;
+ };
++/* Hardware Functions declaration */
++
++/**
++ * reset_select_slave() - reset and select a slave
++ * @sl: the slave to select
++ *
++ * Resets the bus and select the slave by sending a ROM MATCH cmd
++ * w1_reset_select_slave() from w1_io.c could not be used here because
++ * it sent a SKIP ROM command if only one device is on the line.
++ * At the beginning of the such process, sl->master->slave_count is 1 even if
++ * more devices are on the line, causing collision on the line.
++ *
++ * Context: The w1 master lock must be held.
++ *
++ * Return: 0 if success, negative kernel error code otherwise.
++ */
++static int reset_select_slave(struct w1_slave *sl);
++
+ /* Sysfs interface declaration */
+ static ssize_t w1_slave_show(struct device *device,
+@@ -301,7 +320,7 @@ static inline int w1_DS18B20_precision(s
+       while (max_trying--) {
+               crc = 0;
+-              if (!w1_reset_select_slave(sl)) {
++              if (!reset_select_slave(sl)) {
+                       int count = 0;
+                       /* read values to only alter precision bits */
+@@ -314,7 +333,7 @@ static inline int w1_DS18B20_precision(s
+                       if (rom[8] == crc) {
+                               rom[4] = (rom[4] & ~mask) | (precision_bits & mask);
+-                              if (!w1_reset_select_slave(sl)) {
++                              if (!reset_select_slave(sl)) {
+                                       w1_write_8(dev, W1_WRITE_SCRATCHPAD);
+                                       w1_write_8(dev, rom[2]);
+                                       w1_write_8(dev, rom[3]);
+@@ -460,6 +479,21 @@ static void w1_therm_remove_slave(struct
+ /* Hardware Functions */
++/* Safe version of reset_select_slave - avoid using the one in w_io.c */
++static int reset_select_slave(struct w1_slave *sl)
++{
++      u8 match[9] = { W1_MATCH_ROM, };
++      u64 rn = le64_to_cpu(*((u64 *)&sl->reg_num));
++
++      if (w1_reset_bus(sl->master))
++              return -ENODEV;
++
++      memcpy(&match[1], &rn, 8);
++      w1_write_block(sl->master, match, 9);
++
++      return 0;
++}
++
+ static ssize_t read_therm(struct device *device,
+                         struct w1_slave *sl, struct therm_info *info)
+ {
+@@ -487,7 +521,7 @@ static ssize_t read_therm(struct device
+               info->verdict = 0;
+               info->crc = 0;
+-              if (!w1_reset_select_slave(sl)) {
++              if (!reset_select_slave(sl)) {
+                       int count = 0;
+                       unsigned int tm = 750;
+                       unsigned long sleep_rem;
+@@ -495,7 +529,7 @@ static ssize_t read_therm(struct device
+                       w1_write_8(dev, W1_READ_PSUPPLY);
+                       external_power = w1_read_8(dev);
+-                      if (w1_reset_select_slave(sl))
++                      if (reset_select_slave(sl))
+                               continue;
+                       /* 750ms strong pullup (or delay) after the convert */
+@@ -525,7 +559,7 @@ static ssize_t read_therm(struct device
+                               }
+                       }
+-                      if (!w1_reset_select_slave(sl)) {
++                      if (!reset_select_slave(sl)) {
+                               w1_write_8(dev, W1_READ_SCRATCHPAD);
+                               count = w1_read_block(dev, info->rom, 9);
+@@ -577,7 +611,7 @@ static inline int w1_therm_eeprom(struct
+       memset(rom, 0, sizeof(rom));
+       while (max_trying--) {
+-              if (!w1_reset_select_slave(sl)) {
++              if (!reset_select_slave(sl)) {
+                       unsigned int tm = 10;
+                       unsigned long sleep_rem;
+@@ -585,7 +619,7 @@ static inline int w1_therm_eeprom(struct
+                       w1_write_8(dev, W1_READ_PSUPPLY);
+                       external_power = w1_read_8(dev);
+-                      if (w1_reset_select_slave(sl))
++                      if (reset_select_slave(sl))
+                               continue;
+                       /* 10ms strong pullup/delay after the copy command */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0768-w1_therm-adding-ext_power-sysfs-entry.patch b/target/linux/bcm27xx/patches-5.4/950-0768-w1_therm-adding-ext_power-sysfs-entry.patch
new file mode 100644 (file)
index 0000000..b2e8195
--- /dev/null
@@ -0,0 +1,293 @@
+From 5737e27d3c5e2f743421e68f926c05e8581ae21f Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:36:50 +0200
+Subject: [PATCH] w1_therm: adding ext_power sysfs entry
+
+commit b7bb6ca17a90f47c2fe2848531b5bbaf27a65ba7 upstream.
+
+Adding ext_power sysfs entry (RO). Return the power status of the device:
+ - 0: device parasite powered
+ - 1: device externally powered
+ - xx: xx is kernel error
+
+The power status of each device is check when the device is
+discover by the bus master, in 'w1_therm_add_slave(struct w1_slave *)'.
+The status is stored in the device structure w1_therm_family_data so
+that the driver always knows the power state of each device, which could
+be used later to determine the required strong pull up to apply on the
+line.
+
+The power status is re evaluate each time the sysfs ext_power read by
+a user.
+
+The hardware function 'read_powermode(struct w1_slave *sl)' act just as
+per device specifications, sending W1_READ_PSUPPLY command on the bus,
+and issue a read time slot, reading only one bit.
+
+A helper function 'bool bus_mutex_lock(struct mutex *lock)' is introduced.
+It try to aquire the bus mutex several times (W1_THERM_MAX_TRY), waiting
+W1_THERM_RETRY_DELAY between two attempt.
+
+Updating Documentation/ABI/testing/sysfs-driver-w1_therm accordingly.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203650.410439-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../ABI/testing/sysfs-driver-w1_therm         |  29 ++++
+ drivers/w1/slaves/w1_therm.c                  | 137 ++++++++++++++++++
+ 2 files changed, 166 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-driver-w1_therm
+
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
+@@ -0,0 +1,29 @@
++What:         /sys/bus/w1/devices/.../ext_power
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (RO) return the power status by asking the device
++                      * '0': device parasite powered
++                      * '1': device externally powered
++                      * '-xx': xx is kernel error when reading power status
++Users:                any user space application which wants to communicate with
++              w1_term device
++
++
++What:         /sys/bus/w1/devices/.../w1_slave
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (RW) return the temperature in 1/1000 degC.
++              *read*: return 2 lines with the hexa output data sent on the
++              bus, return the CRC check and temperature in 1/1000 degC
++              *write* :
++                      * '0' : save the 2 or 3 bytes to the device EEPROM
++                      (i.e. TH, TL and config register)
++                      * '9..12' : set the device resolution in RAM
++                      (if supported)
++                      * Anything else: do nothing
++              refer to Documentation/w1/slaves/w1_therm.rst for detailed
++              information.
++Users:                any user space application which wants to communicate with
++              w1_term device
+\ No newline at end of file
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -43,8 +43,21 @@
+ static int w1_strong_pullup = 1;
+ module_param_named(strong_pullup, w1_strong_pullup, int, 0);
++/* Nb of try for an operation */
++#define W1_THERM_MAX_TRY              5
++
++/* ms delay to retry bus mutex */
++#define W1_THERM_RETRY_DELAY          20
++
+ /* Helpers Macros */
++/*
++ * return the power mode of the sl slave : 1-ext, 0-parasite, <0 unknown
++ * always test family data existence before using this macro
++ */
++#define SLAVE_POWERMODE(sl) \
++      (((struct w1_therm_family_data *)(sl->family_data))->external_powered)
++
+ /* return the address of the refcnt in the family data */
+ #define THERM_REFCNT(family_data) \
+       (&((struct w1_therm_family_data *)family_data)->refcnt)
+@@ -73,10 +86,14 @@ struct w1_therm_family_converter {
+  * struct w1_therm_family_data - device data
+  * @rom: ROM device id (64bit Lasered ROM code + 1 CRC byte)
+  * @refcnt: ref count
++ * @external_powered: 1 device powered externally,
++ *                            0 device parasite powered,
++ *                            -x error or undefined
+  */
+ struct w1_therm_family_data {
+       uint8_t rom[9];
+       atomic_t refcnt;
++      int external_powered;
+ };
+ /**
+@@ -109,6 +126,20 @@ struct therm_info {
+  */
+ static int reset_select_slave(struct w1_slave *sl);
++/**
++ * read_powermode() - Query the power mode of the slave
++ * @sl: slave to retrieve the power mode
++ *
++ * Ask the device to get its power mode (external or parasite)
++ * and store the power status in the &struct w1_therm_family_data.
++ *
++ * Return:
++ * * 0 parasite powered device
++ * * 1 externally powered device
++ * * <0 kernel error code
++ */
++static int read_powermode(struct w1_slave *sl);
++
+ /* Sysfs interface declaration */
+ static ssize_t w1_slave_show(struct device *device,
+@@ -120,10 +151,14 @@ static ssize_t w1_slave_store(struct dev
+ static ssize_t w1_seq_show(struct device *device,
+       struct device_attribute *attr, char *buf);
++static ssize_t ext_power_show(struct device *device,
++      struct device_attribute *attr, char *buf);
++
+ /* Attributes declarations */
+ static DEVICE_ATTR_RW(w1_slave);
+ static DEVICE_ATTR_RO(w1_seq);
++static DEVICE_ATTR_RO(ext_power);
+ /* Interface Functions declaration */
+@@ -151,12 +186,14 @@ static void w1_therm_remove_slave(struct
+ static struct attribute *w1_therm_attrs[] = {
+       &dev_attr_w1_slave.attr,
++      &dev_attr_ext_power.attr,
+       NULL,
+ };
+ static struct attribute *w1_ds28ea00_attrs[] = {
+       &dev_attr_w1_slave.attr,
+       &dev_attr_w1_seq.attr,
++      &dev_attr_ext_power.attr,
+       NULL,
+ };
+@@ -433,6 +470,34 @@ static struct w1_therm_family_converter
+ /* Helpers Functions */
+ /**
++ * bus_mutex_lock() - Acquire the mutex
++ * @lock: w1 bus mutex to acquire
++ *
++ * It try to acquire the mutex W1_THERM_MAX_TRY times and wait
++ * W1_THERM_RETRY_DELAY between 2 attempts.
++ *
++ * Return: true is mutex is acquired and lock, false otherwise
++ */
++static inline bool bus_mutex_lock(struct mutex *lock)
++{
++      int max_trying = W1_THERM_MAX_TRY;
++
++      /* try to acquire the mutex, if not, sleep retry_delay before retry) */
++      while (mutex_lock_interruptible(lock) != 0 && max_trying > 0) {
++              unsigned long sleep_rem;
++
++              sleep_rem = msleep_interruptible(W1_THERM_RETRY_DELAY);
++              if (!sleep_rem)
++                      max_trying--;
++      }
++
++      if (!max_trying)
++              return false;   /* Didn't acquire the bus mutex */
++
++      return true;
++}
++
++/**
+  * w1_convert_temp() - temperature conversion binding function
+  * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
+  * @fid: device family id
+@@ -461,7 +526,19 @@ static int w1_therm_add_slave(struct w1_
+               GFP_KERNEL);
+       if (!sl->family_data)
+               return -ENOMEM;
++
+       atomic_set(THERM_REFCNT(sl->family_data), 1);
++
++      /* Getting the power mode of the device {external, parasite} */
++      SLAVE_POWERMODE(sl) = read_powermode(sl);
++
++      if (SLAVE_POWERMODE(sl) < 0) {
++              /* no error returned as device has been added */
++              dev_warn(&sl->dev,
++                      "%s: Device has been added, but power_mode may be corrupted. err=%d\n",
++                       __func__, SLAVE_POWERMODE(sl));
++      }
++
+       return 0;
+ }
+@@ -661,6 +738,44 @@ error:
+       return ret;
+ }
++static int read_powermode(struct w1_slave *sl)
++{
++      struct w1_master *dev_master = sl->master;
++      int max_trying = W1_THERM_MAX_TRY;
++      int  ret = -ENODEV;
++
++      if (!sl->family_data)
++              goto error;
++
++      /* prevent the slave from going away in sleep */
++      atomic_inc(THERM_REFCNT(sl->family_data));
++
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
++              goto dec_refcnt;
++      }
++
++      while ((max_trying--) && (ret < 0)) {
++              /* safe version to select slave */
++              if (!reset_select_slave(sl)) {
++                      w1_write_8(dev_master, W1_READ_PSUPPLY);
++                      /*
++                       * Emit a read time slot and read only one bit,
++                       * 1 is externally powered,
++                       * 0 is parasite powered
++                       */
++                      ret = w1_touch_bit(dev_master, 1);
++                      /* ret should be either 1 either 0 */
++              }
++      }
++      mutex_unlock(&dev_master->bus_mutex);
++
++dec_refcnt:
++      atomic_dec(THERM_REFCNT(sl->family_data));
++error:
++      return ret;
++}
++
+ /* Sysfs Interface definition */
+ static ssize_t w1_slave_show(struct device *device,
+@@ -722,6 +837,28 @@ static ssize_t w1_slave_store(struct dev
+       return ret ? : size;
+ }
++static ssize_t ext_power_show(struct device *device,
++      struct device_attribute *attr, char *buf)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++
++      if (!sl->family_data) {
++              dev_info(device,
++                      "%s: Device not supported by the driver\n", __func__);
++              return 0;  /* No device family */
++      }
++
++      /* Getting the power mode of the device {external, parasite} */
++      SLAVE_POWERMODE(sl) = read_powermode(sl);
++
++      if (SLAVE_POWERMODE(sl) < 0) {
++              dev_dbg(device,
++                      "%s: Power_mode may be corrupted. err=%d\n",
++                      __func__, SLAVE_POWERMODE(sl));
++      }
++      return sprintf(buf, "%d\n", SLAVE_POWERMODE(sl));
++}
++
+ #if IS_REACHABLE(CONFIG_HWMON)
+ static int w1_read_temp(struct device *device, u32 attr, int channel,
+                       long *val)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0769-w1_therm-adding-resolution-sysfs-entry.patch b/target/linux/bcm27xx/patches-5.4/950-0769-w1_therm-adding-resolution-sysfs-entry.patch
new file mode 100644 (file)
index 0000000..17b047a
--- /dev/null
@@ -0,0 +1,713 @@
+From feffc2efed02adda00c6c5480292db012663e6e8 Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:37:08 +0200
+Subject: [PATCH] w1_therm: adding resolution sysfs entry
+
+commit 308bdb94de0c1abe7eac5193f58638b8aeaddf4b upstream.
+
+Adding resolution sysfs entry (RW) to get or set the device resolution
+Write values are managed as follow:
+       * '9..12': resolution to set in bit
+       * Anything else: do nothing
+Read values are :
+       * '9..12': device resolution in bit
+       * '-xx': xx is kernel error when reading the resolution
+
+Only supported devices will show the sysfs entry. A new family has been
+created for DS18S20 devices as they do not implement resolution feature.
+
+The resolution of each device is check when the device is
+discover by the bus master, in 'w1_therm_add_slave(struct w1_slave *)'.
+The status is stored in the device structure w1_therm_family_data so
+that the driver always knows the resolution of each device, which could
+be used later to determine the required conversion duration (resolution
+dependent).
+
+The resolution is re evaluate each time a user read or write the sysfs
+entry.
+
+To avoid looping through the w1_therm_families at run time, the pointer
+'specific_functions' is set up to the correct 'w1_therm_family_converter'
+when the slave is added (which mean when it is discovered by the master).
+This initialization is done by a helper function
+'device_family(struct w1_slave *sl)', and a dedicated macro
+'SLAVE_SPECIFIC_FUNC(sl)' allow the access to the specific function of the
+slave device.
+
+'read_scratchpad' and 'write_scratchpad' are the hardware functions to
+access the device RAM, as per protocol specification.
+
+It cancel the former 'precision' functions, which was only set and never
+read (so not stored in the device struct).
+
+Updating Documentation/ABI/testing/sysfs-driver-w1_therm accordingly.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203708.410649-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../ABI/testing/sysfs-driver-w1_therm         |  17 +
+ drivers/w1/slaves/w1_therm.c                  | 442 ++++++++++++++----
+ 2 files changed, 361 insertions(+), 98 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-driver-w1_therm
++++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
+@@ -10,6 +10,23 @@ Users:              any user space application which
+               w1_term device
++What:         /sys/bus/w1/devices/.../resolution
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (RW) get or set the device resolution (on supported devices,
++              if not, this entry is not present). Note that the resolution
++              will be changed only in device RAM, so it will be cleared when
++              power is lost. Trigger a 'save' to EEPROM command to keep
++              values after power-on. Read or write are :
++                      * '9..12': device resolution in bit
++                      or resolution to set in bit
++                      * '-xx': xx is kernel error when reading the resolution
++                      * Anything else: do nothing
++Users:                any user space application which wants to communicate with
++              w1_term device
++
++
+ What:         /sys/bus/w1/devices/.../w1_slave
+ Date:         May 2020
+ Contact:      Akira Shimahara <akira215corp@gmail.com>
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -52,12 +52,26 @@ module_param_named(strong_pullup, w1_str
+ /* Helpers Macros */
+ /*
++ * return a pointer on the slave w1_therm_family_converter struct:
++ * always test family data existence before using this macro
++ */
++#define SLAVE_SPECIFIC_FUNC(sl) \
++      (((struct w1_therm_family_data *)(sl->family_data))->specific_functions)
++
++/*
+  * return the power mode of the sl slave : 1-ext, 0-parasite, <0 unknown
+  * always test family data existence before using this macro
+  */
+ #define SLAVE_POWERMODE(sl) \
+       (((struct w1_therm_family_data *)(sl->family_data))->external_powered)
++/*
++ * return the resolution in bit of the sl slave : <0 unknown
++ * always test family data existence before using this macro
++ */
++#define SLAVE_RESOLUTION(sl) \
++      (((struct w1_therm_family_data *)(sl->family_data))->resolution)
++
+ /* return the address of the refcnt in the family data */
+ #define THERM_REFCNT(family_data) \
+       (&((struct w1_therm_family_data *)family_data)->refcnt)
+@@ -70,7 +84,8 @@ module_param_named(strong_pullup, w1_str
+  * @reserved: not used here
+  * @f: pointer to the device binding structure
+  * @convert: pointer to the device conversion function
+- * @precision: pointer to the device precision function
++ * @set_resolution: pointer to the device set_resolution function
++ * @get_resolution: pointer to the device get_resolution function
+  * @eeprom: pointer to eeprom function
+  */
+ struct w1_therm_family_converter {
+@@ -78,7 +93,8 @@ struct w1_therm_family_converter {
+       u16             reserved;
+       struct w1_family        *f;
+       int             (*convert)(u8 rom[9]);
+-      int             (*precision)(struct device *device, int val);
++      int             (*set_resolution)(struct w1_slave *sl, int val);
++      int             (*get_resolution)(struct w1_slave *sl);
+       int             (*eeprom)(struct device *device);
+ };
+@@ -89,11 +105,15 @@ struct w1_therm_family_converter {
+  * @external_powered: 1 device powered externally,
+  *                            0 device parasite powered,
+  *                            -x error or undefined
++ * @resolution: current device resolution
++ * @specific_functions: pointer to struct of device specific function
+  */
+ struct w1_therm_family_data {
+       uint8_t rom[9];
+       atomic_t refcnt;
+       int external_powered;
++      int resolution;
++      struct w1_therm_family_converter *specific_functions;
+ };
+ /**
+@@ -127,6 +147,25 @@ struct therm_info {
+ static int reset_select_slave(struct w1_slave *sl);
+ /**
++ * read_scratchpad() - read the data in device RAM
++ * @sl: pointer to the slave to read
++ * @info: pointer to a structure to store the read results
++ *
++ * Return: 0 if success, -kernel error code otherwise
++ */
++static int read_scratchpad(struct w1_slave *sl, struct therm_info *info);
++
++/**
++ * write_scratchpad() - write nb_bytes in the device RAM
++ * @sl: pointer to the slave to write in
++ * @data: pointer to an array of 3 bytes, as 3 bytes MUST be written
++ * @nb_bytes: number of bytes to be written (2 for DS18S20, 3 otherwise)
++ *
++ * Return: 0 if success, -kernel error code otherwise
++ */
++static int write_scratchpad(struct w1_slave *sl, const u8 *data, u8 nb_bytes);
++
++/**
+  * read_powermode() - Query the power mode of the slave
+  * @sl: slave to retrieve the power mode
+  *
+@@ -154,11 +193,18 @@ static ssize_t w1_seq_show(struct device
+ static ssize_t ext_power_show(struct device *device,
+       struct device_attribute *attr, char *buf);
++static ssize_t resolution_show(struct device *device,
++      struct device_attribute *attr, char *buf);
++
++static ssize_t resolution_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size);
++
+ /* Attributes declarations */
+ static DEVICE_ATTR_RW(w1_slave);
+ static DEVICE_ATTR_RO(w1_seq);
+ static DEVICE_ATTR_RO(ext_power);
++static DEVICE_ATTR_RW(resolution);
+ /* Interface Functions declaration */
+@@ -187,6 +233,13 @@ static void w1_therm_remove_slave(struct
+ static struct attribute *w1_therm_attrs[] = {
+       &dev_attr_w1_slave.attr,
+       &dev_attr_ext_power.attr,
++      &dev_attr_resolution.attr,
++      NULL,
++};
++
++static struct attribute *w1_ds18s20_attrs[] = {
++      &dev_attr_w1_slave.attr,
++      &dev_attr_ext_power.attr,
+       NULL,
+ };
+@@ -194,12 +247,14 @@ static struct attribute *w1_ds28ea00_att
+       &dev_attr_w1_slave.attr,
+       &dev_attr_w1_seq.attr,
+       &dev_attr_ext_power.attr,
++      &dev_attr_resolution.attr,
+       NULL,
+ };
+ /* Attribute groups */
+ ATTRIBUTE_GROUPS(w1_therm);
++ATTRIBUTE_GROUPS(w1_ds18s20);
+ ATTRIBUTE_GROUPS(w1_ds28ea00);
+ #if IS_REACHABLE(CONFIG_HWMON)
+@@ -261,6 +316,13 @@ static struct w1_family_ops w1_therm_fop
+       .chip_info      = W1_CHIPINFO,
+ };
++static struct w1_family_ops w1_ds18s20_fops = {
++      .add_slave      = w1_therm_add_slave,
++      .remove_slave   = w1_therm_remove_slave,
++      .groups         = w1_ds18s20_groups,
++      .chip_info      = W1_CHIPINFO,
++};
++
+ static struct w1_family_ops w1_ds28ea00_fops = {
+       .add_slave      = w1_therm_add_slave,
+       .remove_slave   = w1_therm_remove_slave,
+@@ -272,7 +334,7 @@ static struct w1_family_ops w1_ds28ea00_
+ static struct w1_family w1_therm_family_DS18S20 = {
+       .fid = W1_THERM_DS18S20,
+-      .fops = &w1_therm_fops,
++      .fops = &w1_ds18s20_fops,
+ };
+ static struct w1_family w1_therm_family_DS18B20 = {
+@@ -300,92 +362,67 @@ static struct w1_family w1_therm_family_
+ /* write configuration to eeprom */
+ static inline int w1_therm_eeprom(struct device *device);
+-/* DS18S20 does not feature configuration register */
+-static inline int w1_DS18S20_precision(struct device *device, int val)
++static inline int w1_DS18B20_write_data(struct w1_slave *sl,
++                              const u8 *data)
+ {
+-      return 0;
++      return write_scratchpad(sl, data, 3);
+ }
+-/* Set precision for conversion */
+-static inline int w1_DS18B20_precision(struct device *device, int val)
++static inline int w1_DS18S20_write_data(struct w1_slave *sl,
++                              const u8 *data)
+ {
+-      struct w1_slave *sl = dev_to_w1_slave(device);
+-      struct w1_master *dev = sl->master;
+-      u8 rom[9], crc;
+-      int ret, max_trying = 10;
+-      u8 *family_data = sl->family_data;
+-      uint8_t precision_bits;
+-      uint8_t mask = 0x60;
+-
+-      if (val > 12 || val < 9) {
+-              pr_warn("Unsupported precision\n");
+-              ret = -EINVAL;
+-              goto error;
+-      }
+-
+-      if (!sl->family_data) {
+-              ret = -ENODEV;
+-              goto error;
+-      }
+-
+-      /* prevent the slave from going away in sleep */
+-      atomic_inc(THERM_REFCNT(family_data));
++      /* No config register */
++      return write_scratchpad(sl, data, 2);
++}
+-      ret = mutex_lock_interruptible(&dev->bus_mutex);
+-      if (ret != 0)
+-              goto dec_refcnt;
++static inline int w1_DS18B20_set_resolution(struct w1_slave *sl, int val)
++{
++      int ret = -ENODEV;
++      u8 new_config_register[3];      /* array of data to be written */
++      struct therm_info info;
+-      memset(rom, 0, sizeof(rom));
++      /* resolution of DS18B20 is in the range [9..12] bits */
++      if (val < 9 || val > 12)
++              return -EINVAL;
++
++      val -= 9; /* soustract 9 the lowest resolution in bit */
++      val = (val << 5); /* shift to position bit 5 & bit 6 */
++
++      /*
++       * Read the scratchpad to change only the required bits
++       * (bit5 & bit 6 from byte 4)
++       */
++      ret = read_scratchpad(sl, &info);
++      if (!ret) {
++              new_config_register[0] = info.rom[2];
++              new_config_register[1] = info.rom[3];
++              /* config register is byte 4 & mask 0b10011111*/
++              new_config_register[2] = (info.rom[4] & 0x9F) |
++                                      (u8) val;
++      } else
++              return ret;
+-      /* translate precision to bitmask (see datasheet page 9) */
+-      switch (val) {
+-      case 9:
+-              precision_bits = 0x00;
+-              break;
+-      case 10:
+-              precision_bits = 0x20;
+-              break;
+-      case 11:
+-              precision_bits = 0x40;
+-              break;
+-      case 12:
+-      default:
+-              precision_bits = 0x60;
+-              break;
+-      }
++      /* Write data in the device RAM */
++      ret = w1_DS18B20_write_data(sl, new_config_register);
+-      while (max_trying--) {
+-              crc = 0;
++      return ret;
++}
+-              if (!reset_select_slave(sl)) {
+-                      int count = 0;
++static inline int w1_DS18B20_get_resolution(struct w1_slave *sl)
++{
++      int ret = -ENODEV;
++      u8 config_register;
++      struct therm_info info;
+-                      /* read values to only alter precision bits */
+-                      w1_write_8(dev, W1_READ_SCRATCHPAD);
+-                      count = w1_read_block(dev, rom, 9);
+-                      if (count != 9)
+-                              dev_warn(device, "w1_read_block() returned %u instead of 9.\n", count);
+-
+-                      crc = w1_calc_crc8(rom, 8);
+-                      if (rom[8] == crc) {
+-                              rom[4] = (rom[4] & ~mask) | (precision_bits & mask);
+-
+-                              if (!reset_select_slave(sl)) {
+-                                      w1_write_8(dev, W1_WRITE_SCRATCHPAD);
+-                                      w1_write_8(dev, rom[2]);
+-                                      w1_write_8(dev, rom[3]);
+-                                      w1_write_8(dev, rom[4]);
++      ret = read_scratchpad(sl, &info);
+-                                      break;
+-                              }
+-                      }
+-              }
++      if (!ret)       {
++              config_register = info.rom[4]; /* config register is byte 4 */
++              config_register &= 0x60; /* 0b01100000 keep only bit 5 & 6 */
++              config_register = (config_register >> 5);       /* shift */
++              config_register += 9; /* add 9 the lowest resolution in bit */
++              ret = (int) config_register;
+       }
+-
+-      mutex_unlock(&dev->bus_mutex);
+-dec_refcnt:
+-      atomic_dec(THERM_REFCNT(family_data));
+-error:
+       return ret;
+ }
+@@ -438,31 +475,36 @@ static struct w1_therm_family_converter
+       {
+               .f              = &w1_therm_family_DS18S20,
+               .convert        = w1_DS18S20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
++              .set_resolution = NULL, /* no config register */
++              .get_resolution = NULL, /* no config register */
+               .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS1822,
+               .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
++              .set_resolution = w1_DS18B20_set_resolution,
++              .get_resolution = w1_DS18B20_get_resolution,
+               .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS18B20,
+               .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18B20_precision,
++              .set_resolution = w1_DS18B20_set_resolution,
++              .get_resolution = w1_DS18B20_get_resolution,
+               .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS28EA00,
+               .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
++              .set_resolution = w1_DS18B20_set_resolution,
++              .get_resolution = w1_DS18B20_get_resolution,
+               .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS1825,
+               .convert        = w1_DS18B20_convert_temp,
+-              .precision      = w1_DS18S20_precision,
++              .set_resolution = w1_DS18B20_set_resolution,
++              .get_resolution = w1_DS18B20_get_resolution,
+               .eeprom         = w1_therm_eeprom
+       }
+ };
+@@ -470,6 +512,26 @@ static struct w1_therm_family_converter
+ /* Helpers Functions */
+ /**
++ * device_family() - Retrieve a pointer on &struct w1_therm_family_converter
++ * @sl: slave to retrieve the device specific structure
++ *
++ * Return: pointer to the slaves's family converter, NULL if not known
++ */
++static struct w1_therm_family_converter *device_family(struct w1_slave *sl)
++{
++      struct w1_therm_family_converter *ret = NULL;
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
++              if (w1_therm_families[i].f->fid == sl->family->fid) {
++                      ret = &w1_therm_families[i];
++                      break;
++              }
++      }
++      return ret;
++}
++
++/**
+  * bus_mutex_lock() - Acquire the mutex
+  * @lock: w1 bus mutex to acquire
+  *
+@@ -522,6 +584,9 @@ static inline int w1_convert_temp(u8 rom
+ static int w1_therm_add_slave(struct w1_slave *sl)
+ {
++      struct w1_therm_family_converter *sl_family_conv;
++
++      /* Allocate memory */
+       sl->family_data = kzalloc(sizeof(struct w1_therm_family_data),
+               GFP_KERNEL);
+       if (!sl->family_data)
+@@ -529,6 +594,15 @@ static int w1_therm_add_slave(struct w1_
+       atomic_set(THERM_REFCNT(sl->family_data), 1);
++      /* Get a pointer to the device specific function struct */
++      sl_family_conv = device_family(sl);
++      if (!sl_family_conv) {
++              kfree(sl->family_data);
++              return -ENODEV;
++      }
++      /* save this pointer to the device structure */
++      SLAVE_SPECIFIC_FUNC(sl) = sl_family_conv;
++
+       /* Getting the power mode of the device {external, parasite} */
+       SLAVE_POWERMODE(sl) = read_powermode(sl);
+@@ -539,6 +613,18 @@ static int w1_therm_add_slave(struct w1_
+                        __func__, SLAVE_POWERMODE(sl));
+       }
++      /* Getting the resolution of the device */
++      if (SLAVE_SPECIFIC_FUNC(sl)->get_resolution) {
++              SLAVE_RESOLUTION(sl) =
++                      SLAVE_SPECIFIC_FUNC(sl)->get_resolution(sl);
++              if (SLAVE_RESOLUTION(sl) < 0) {
++                      /* no error returned as device has been added */
++                      dev_warn(&sl->dev,
++                              "%s:Device has been added, but resolution may be corrupted. err=%d\n",
++                              __func__, SLAVE_RESOLUTION(sl));
++              }
++      }
++
+       return 0;
+ }
+@@ -665,6 +751,93 @@ error:
+       return ret;
+ }
++static int read_scratchpad(struct w1_slave *sl, struct therm_info *info)
++{
++      struct w1_master *dev_master = sl->master;
++      int max_trying = W1_THERM_MAX_TRY;
++      int ret = -ENODEV;
++
++      info->verdict = 0;
++
++      if (!sl->family_data)
++              goto error;
++
++      memset(info->rom, 0, sizeof(info->rom));
++
++      /* prevent the slave from going away in sleep */
++      atomic_inc(THERM_REFCNT(sl->family_data));
++
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
++              goto dec_refcnt;
++      }
++
++      while (max_trying-- && ret) { /* ret should be 0 */
++              /* safe version to select slave */
++              if (!reset_select_slave(sl)) {
++                      u8 nb_bytes_read;
++
++                      w1_write_8(dev_master, W1_READ_SCRATCHPAD);
++
++                      nb_bytes_read = w1_read_block(dev_master, info->rom, 9);
++                      if (nb_bytes_read != 9) {
++                              dev_warn(&sl->dev,
++                                      "w1_read_block(): returned %u instead of 9.\n",
++                                      nb_bytes_read);
++                              ret = -EIO;
++                      }
++
++                      info->crc = w1_calc_crc8(info->rom, 8);
++
++                      if (info->rom[8] == info->crc) {
++                              info->verdict = 1;
++                              ret = 0;
++                      } else
++                              ret = -EIO; /* CRC not checked */
++              }
++
++      }
++      mutex_unlock(&dev_master->bus_mutex);
++
++dec_refcnt:
++      atomic_dec(THERM_REFCNT(sl->family_data));
++error:
++      return ret;
++}
++
++static int write_scratchpad(struct w1_slave *sl, const u8 *data, u8 nb_bytes)
++{
++      struct w1_master *dev_master = sl->master;
++      int max_trying = W1_THERM_MAX_TRY;
++      int ret = -ENODEV;
++
++      if (!sl->family_data)
++              goto error;
++
++      /* prevent the slave from going away in sleep */
++      atomic_inc(THERM_REFCNT(sl->family_data));
++
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
++              goto dec_refcnt;
++      }
++
++      while (max_trying-- && ret) { /* ret should be 0 */
++              /* safe version to select slave */
++              if (!reset_select_slave(sl)) {
++                      w1_write_8(dev_master, W1_WRITE_SCRATCHPAD);
++                      w1_write_block(dev_master, data, nb_bytes);
++                      ret = 0;
++              }
++      }
++      mutex_unlock(&dev_master->bus_mutex);
++
++dec_refcnt:
++      atomic_dec(THERM_REFCNT(sl->family_data));
++error:
++      return ret;
++}
++
+ static inline int w1_therm_eeprom(struct device *device)
+ {
+       struct w1_slave *sl = dev_to_w1_slave(device);
+@@ -815,26 +988,38 @@ static ssize_t w1_slave_store(struct dev
+                             struct device_attribute *attr, const char *buf,
+                             size_t size)
+ {
+-      int val, ret;
++      int val, ret = 0;
+       struct w1_slave *sl = dev_to_w1_slave(device);
+-      int i;
+-      ret = kstrtoint(buf, 0, &val);
+-      if (ret)
+-              return ret;
++      ret = kstrtoint(buf, 10, &val); /* converting user entry to int */
+-      for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
+-              if (w1_therm_families[i].f->fid == sl->family->fid) {
+-      /* zero value indicates to write current configuration to eeprom */
+-                      if (val == 0)
+-                              ret = w1_therm_families[i].eeprom(device);
+-                      else
+-                              ret = w1_therm_families[i].precision(device,
+-                                                                      val);
+-                      break;
+-              }
++      if (ret) {      /* conversion error */
++              dev_info(device,
++                      "%s: conversion error. err= %d\n", __func__, ret);
++              return size;    /* return size to avoid call back again */
++      }
++
++      if ((!sl->family_data) || (!SLAVE_SPECIFIC_FUNC(sl))) {
++              dev_info(device,
++                      "%s: Device not supported by the driver\n", __func__);
++              return size;  /* No device family */
++      }
++
++      if (val == 0)   /* val=0 : trigger a EEPROM save */
++              ret = SLAVE_SPECIFIC_FUNC(sl)->eeprom(device);
++      else {
++              if (SLAVE_SPECIFIC_FUNC(sl)->set_resolution)
++                      ret = SLAVE_SPECIFIC_FUNC(sl)->set_resolution(sl, val);
+       }
+-      return ret ? : size;
++
++      if (ret) {
++              dev_info(device,
++                      "%s: writing error %d\n", __func__, ret);
++              /* return size to avoid call back again */
++      } else
++              SLAVE_RESOLUTION(sl) = val;
++
++      return size; /* always return size to avoid infinite calling */
+ }
+ static ssize_t ext_power_show(struct device *device,
+@@ -859,6 +1044,67 @@ static ssize_t ext_power_show(struct dev
+       return sprintf(buf, "%d\n", SLAVE_POWERMODE(sl));
+ }
++static ssize_t resolution_show(struct device *device,
++      struct device_attribute *attr, char *buf)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++
++      if ((!sl->family_data) || (!SLAVE_SPECIFIC_FUNC(sl))) {
++              dev_info(device,
++                      "%s: Device not supported by the driver\n", __func__);
++              return 0;  /* No device family */
++      }
++
++      /* get the correct function depending on the device */
++      SLAVE_RESOLUTION(sl) = SLAVE_SPECIFIC_FUNC(sl)->get_resolution(sl);
++      if (SLAVE_RESOLUTION(sl) < 0) {
++              dev_dbg(device,
++                      "%s: Resolution may be corrupted. err=%d\n",
++                      __func__, SLAVE_RESOLUTION(sl));
++      }
++
++      return sprintf(buf, "%d\n", SLAVE_RESOLUTION(sl));
++}
++
++static ssize_t resolution_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      int val;
++      int ret = 0;
++
++      ret = kstrtoint(buf, 10, &val); /* converting user entry to int */
++
++      if (ret) {      /* conversion error */
++              dev_info(device,
++                      "%s: conversion error. err= %d\n", __func__, ret);
++              return size;    /* return size to avoid call back again */
++      }
++
++      if ((!sl->family_data) || (!SLAVE_SPECIFIC_FUNC(sl))) {
++              dev_info(device,
++                      "%s: Device not supported by the driver\n", __func__);
++              return size;  /* No device family */
++      }
++
++      /*
++       * Don't deal with the val enterd by user,
++       * only device knows what is correct or not
++       */
++
++      /* get the correct function depending on the device */
++      ret = SLAVE_SPECIFIC_FUNC(sl)->set_resolution(sl, val);
++
++      if (ret) {
++              dev_info(device,
++                      "%s: writing error %d\n", __func__, ret);
++              /* return size to avoid call back again */
++      } else
++              SLAVE_RESOLUTION(sl) = val;
++
++      return size;
++}
++
+ #if IS_REACHABLE(CONFIG_HWMON)
+ static int w1_read_temp(struct device *device, u32 attr, int channel,
+                       long *val)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0770-w1_therm-adding-eeprom-sysfs-entry.patch b/target/linux/bcm27xx/patches-5.4/950-0770-w1_therm-adding-eeprom-sysfs-entry.patch
new file mode 100644 (file)
index 0000000..58467a0
--- /dev/null
@@ -0,0 +1,372 @@
+From 855a8d82506c7c2428e13beebe8dbf7739ea6176 Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:37:25 +0200
+Subject: [PATCH] w1_therm: adding eeprom sysfs entry
+
+commit 45d457a4cf24455eefd076a01a3d86414fc2ff1e upstream.
+
+The driver implement 2 hardware functions to access device RAM:
+ * copy_scratchpad
+ * recall_scratchpad
+They act according to device specifications.
+
+As EEPROM operations are not device dependent (all w1_therm can perform
+EEPROM read/write operation following the same protocol), it is removed
+from device families structures.
+
+Updating Documentation/ABI/testing/sysfs-driver-w1_therm accordingly.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203725.410844-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../ABI/testing/sysfs-driver-w1_therm         |  14 ++
+ drivers/w1/slaves/w1_therm.c                  | 175 ++++++++++++------
+ 2 files changed, 132 insertions(+), 57 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-driver-w1_therm
++++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
+@@ -1,3 +1,17 @@
++What:         /sys/bus/w1/devices/.../eeprom
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (WO) writing that file will either trigger a save of the
++              device data to its embedded EEPROM, either restore data
++              embedded in device EEPROM. Be aware that devices support
++              limited EEPROM writing cycles (typical 50k)
++                      * 'save': save device RAM to EEPROM
++                      * 'restore': restore EEPROM data in device RAM
++Users:                any user space application which wants to communicate with
++              w1_term device
++
++
+ What:         /sys/bus/w1/devices/.../ext_power
+ Date:         May 2020
+ Contact:      Akira Shimahara <akira215corp@gmail.com>
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -43,12 +43,21 @@
+ static int w1_strong_pullup = 1;
+ module_param_named(strong_pullup, w1_strong_pullup, int, 0);
++/* This command should be in public header w1.h but is not */
++#define W1_RECALL_EEPROM      0xB8
++
+ /* Nb of try for an operation */
+ #define W1_THERM_MAX_TRY              5
+ /* ms delay to retry bus mutex */
+ #define W1_THERM_RETRY_DELAY          20
++/* delay in ms to write in EEPROM */
++#define W1_THERM_EEPROM_WRITE_DELAY   10
++
++#define EEPROM_CMD_WRITE    "save"    /* cmd for write eeprom sysfs */
++#define EEPROM_CMD_READ     "restore" /* cmd for read eeprom sysfs */
++
+ /* Helpers Macros */
+ /*
+@@ -86,7 +95,6 @@ module_param_named(strong_pullup, w1_str
+  * @convert: pointer to the device conversion function
+  * @set_resolution: pointer to the device set_resolution function
+  * @get_resolution: pointer to the device get_resolution function
+- * @eeprom: pointer to eeprom function
+  */
+ struct w1_therm_family_converter {
+       u8              broken;
+@@ -95,7 +103,6 @@ struct w1_therm_family_converter {
+       int             (*convert)(u8 rom[9]);
+       int             (*set_resolution)(struct w1_slave *sl, int val);
+       int             (*get_resolution)(struct w1_slave *sl);
+-      int             (*eeprom)(struct device *device);
+ };
+ /**
+@@ -166,6 +173,22 @@ static int read_scratchpad(struct w1_sla
+ static int write_scratchpad(struct w1_slave *sl, const u8 *data, u8 nb_bytes);
+ /**
++ * copy_scratchpad() - Copy the content of scratchpad in device EEPROM
++ * @sl: slave involved
++ *
++ * Return: 0 if success, -kernel error code otherwise
++ */
++static int copy_scratchpad(struct w1_slave *sl);
++
++/**
++ * recall_eeprom() - Restore EEPROM data to device RAM
++ * @sl: slave involved
++ *
++ * Return: 0 if success, -kernel error code otherwise
++ */
++static int recall_eeprom(struct w1_slave *sl);
++
++/**
+  * read_powermode() - Query the power mode of the slave
+  * @sl: slave to retrieve the power mode
+  *
+@@ -199,12 +222,16 @@ static ssize_t resolution_show(struct de
+ static ssize_t resolution_store(struct device *device,
+       struct device_attribute *attr, const char *buf, size_t size);
++static ssize_t eeprom_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size);
++
+ /* Attributes declarations */
+ static DEVICE_ATTR_RW(w1_slave);
+ static DEVICE_ATTR_RO(w1_seq);
+ static DEVICE_ATTR_RO(ext_power);
+ static DEVICE_ATTR_RW(resolution);
++static DEVICE_ATTR_WO(eeprom);
+ /* Interface Functions declaration */
+@@ -234,12 +261,14 @@ static struct attribute *w1_therm_attrs[
+       &dev_attr_w1_slave.attr,
+       &dev_attr_ext_power.attr,
+       &dev_attr_resolution.attr,
++      &dev_attr_eeprom.attr,
+       NULL,
+ };
+ static struct attribute *w1_ds18s20_attrs[] = {
+       &dev_attr_w1_slave.attr,
+       &dev_attr_ext_power.attr,
++      &dev_attr_eeprom.attr,
+       NULL,
+ };
+@@ -248,6 +277,7 @@ static struct attribute *w1_ds28ea00_att
+       &dev_attr_w1_seq.attr,
+       &dev_attr_ext_power.attr,
+       &dev_attr_resolution.attr,
++      &dev_attr_eeprom.attr,
+       NULL,
+ };
+@@ -359,9 +389,6 @@ static struct w1_family w1_therm_family_
+ /* Device dependent func */
+-/* write configuration to eeprom */
+-static inline int w1_therm_eeprom(struct device *device);
+-
+ static inline int w1_DS18B20_write_data(struct w1_slave *sl,
+                               const u8 *data)
+ {
+@@ -477,35 +504,30 @@ static struct w1_therm_family_converter
+               .convert        = w1_DS18S20_convert_temp,
+               .set_resolution = NULL, /* no config register */
+               .get_resolution = NULL, /* no config register */
+-              .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS1822,
+               .convert        = w1_DS18B20_convert_temp,
+               .set_resolution = w1_DS18B20_set_resolution,
+               .get_resolution = w1_DS18B20_get_resolution,
+-              .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS18B20,
+               .convert        = w1_DS18B20_convert_temp,
+               .set_resolution = w1_DS18B20_set_resolution,
+               .get_resolution = w1_DS18B20_get_resolution,
+-              .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS28EA00,
+               .convert        = w1_DS18B20_convert_temp,
+               .set_resolution = w1_DS18B20_set_resolution,
+               .get_resolution = w1_DS18B20_get_resolution,
+-              .eeprom         = w1_therm_eeprom
+       },
+       {
+               .f              = &w1_therm_family_DS1825,
+               .convert        = w1_DS18B20_convert_temp,
+               .set_resolution = w1_DS18B20_set_resolution,
+               .get_resolution = w1_DS18B20_get_resolution,
+-              .eeprom         = w1_therm_eeprom
+       }
+ };
+@@ -838,75 +860,94 @@ error:
+       return ret;
+ }
+-static inline int w1_therm_eeprom(struct device *device)
++static int copy_scratchpad(struct w1_slave *sl)
+ {
+-      struct w1_slave *sl = dev_to_w1_slave(device);
+-      struct w1_master *dev = sl->master;
+-      u8 rom[9], external_power;
+-      int ret, max_trying = 10;
+-      u8 *family_data = sl->family_data;
++      struct w1_master *dev_master = sl->master;
++      int max_trying = W1_THERM_MAX_TRY;
++      int t_write, ret = -ENODEV;
++      bool strong_pullup;
+-      if (!sl->family_data) {
+-              ret = -ENODEV;
++      if (!sl->family_data)
+               goto error;
+-      }
++
++      t_write = W1_THERM_EEPROM_WRITE_DELAY;
++      strong_pullup = (w1_strong_pullup == 2 ||
++                                      (!SLAVE_POWERMODE(sl) &&
++                                      w1_strong_pullup));
+       /* prevent the slave from going away in sleep */
+-      atomic_inc(THERM_REFCNT(family_data));
++      atomic_inc(THERM_REFCNT(sl->family_data));
+-      ret = mutex_lock_interruptible(&dev->bus_mutex);
+-      if (ret != 0)
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
+               goto dec_refcnt;
++      }
+-      memset(rom, 0, sizeof(rom));
+-
+-      while (max_trying--) {
++      while (max_trying-- && ret) { /* ret should be 0 */
++              /* safe version to select slave */
+               if (!reset_select_slave(sl)) {
+-                      unsigned int tm = 10;
+                       unsigned long sleep_rem;
+-                      /* check if in parasite mode */
+-                      w1_write_8(dev, W1_READ_PSUPPLY);
+-                      external_power = w1_read_8(dev);
+-
+-                      if (reset_select_slave(sl))
+-                              continue;
+-
+-                      /* 10ms strong pullup/delay after the copy command */
+-                      if (w1_strong_pullup == 2 ||
+-                          (!external_power && w1_strong_pullup))
+-                              w1_next_pullup(dev, tm);
+-
+-                      w1_write_8(dev, W1_COPY_SCRATCHPAD);
+-
+-                      if (external_power) {
+-                              mutex_unlock(&dev->bus_mutex);
++                      /* 10ms strong pullup (or delay) after the convert */
++                      if (strong_pullup)
++                              w1_next_pullup(dev_master, t_write);
+-                              sleep_rem = msleep_interruptible(tm);
+-                              if (sleep_rem != 0) {
+-                                      ret = -EINTR;
+-                                      goto dec_refcnt;
+-                              }
++                      w1_write_8(dev_master, W1_COPY_SCRATCHPAD);
+-                              ret = mutex_lock_interruptible(&dev->bus_mutex);
+-                              if (ret != 0)
+-                                      goto dec_refcnt;
+-                      } else if (!w1_strong_pullup) {
+-                              sleep_rem = msleep_interruptible(tm);
++                      if (strong_pullup) {
++                              sleep_rem = msleep_interruptible(t_write);
+                               if (sleep_rem != 0) {
+                                       ret = -EINTR;
+                                       goto mt_unlock;
+                               }
+                       }
+-
+-                      break;
++                      ret = 0;
+               }
++
+       }
+ mt_unlock:
+-      mutex_unlock(&dev->bus_mutex);
++      mutex_unlock(&dev_master->bus_mutex);
+ dec_refcnt:
+-      atomic_dec(THERM_REFCNT(family_data));
++      atomic_dec(THERM_REFCNT(sl->family_data));
++error:
++      return ret;
++}
++
++static int recall_eeprom(struct w1_slave *sl)
++{
++      struct w1_master *dev_master = sl->master;
++      int max_trying = W1_THERM_MAX_TRY;
++      int ret = -ENODEV;
++
++      if (!sl->family_data)
++              goto error;
++
++      /* prevent the slave from going away in sleep */
++      atomic_inc(THERM_REFCNT(sl->family_data));
++
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
++              goto dec_refcnt;
++      }
++
++      while (max_trying-- && ret) { /* ret should be 0 */
++              /* safe version to select slave */
++              if (!reset_select_slave(sl)) {
++
++                      w1_write_8(dev_master, W1_RECALL_EEPROM);
++
++                      ret = 1; /* Slave will pull line to 0 */
++                      while (ret)
++                              ret = 1 - w1_touch_bit(dev_master, 1);
++              }
++
++      }
++
++      mutex_unlock(&dev_master->bus_mutex);
++
++dec_refcnt:
++      atomic_dec(THERM_REFCNT(sl->family_data));
+ error:
+       return ret;
+ }
+@@ -1006,7 +1047,7 @@ static ssize_t w1_slave_store(struct dev
+       }
+       if (val == 0)   /* val=0 : trigger a EEPROM save */
+-              ret = SLAVE_SPECIFIC_FUNC(sl)->eeprom(device);
++              ret = copy_scratchpad(sl);
+       else {
+               if (SLAVE_SPECIFIC_FUNC(sl)->set_resolution)
+                       ret = SLAVE_SPECIFIC_FUNC(sl)->set_resolution(sl, val);
+@@ -1104,6 +1145,26 @@ static ssize_t resolution_store(struct d
+       return size;
+ }
++
++static ssize_t eeprom_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      int ret = -EINVAL; /* Invalid argument */
++
++      if (size == sizeof(EEPROM_CMD_WRITE)) {
++              if (!strncmp(buf, EEPROM_CMD_WRITE, sizeof(EEPROM_CMD_WRITE)-1))
++                      ret = copy_scratchpad(sl);
++      } else if (size == sizeof(EEPROM_CMD_READ)) {
++              if (!strncmp(buf, EEPROM_CMD_READ, sizeof(EEPROM_CMD_READ)-1))
++                      ret = recall_eeprom(sl);
++      }
++
++      if (ret)
++              dev_info(device, "%s: error in process %d\n", __func__, ret);
++
++      return size;
++}
+ #if IS_REACHABLE(CONFIG_HWMON)
+ static int w1_read_temp(struct device *device, u32 attr, int channel,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch b/target/linux/bcm27xx/patches-5.4/950-0771-w1_therm-optimizing-temperature-read-timings.patch
new file mode 100644 (file)
index 0000000..142560c
--- /dev/null
@@ -0,0 +1,528 @@
+From 23769ad113407ceb21a4285a8194c7d788149269 Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:37:42 +0200
+Subject: [PATCH] w1_therm: optimizing temperature read timings
+
+commit 67b392f7b8edfa6f427fecd98722acab34c1c99f upstream.
+
+Optimizing temperature reading by reducing waiting conversion time
+according to device resolution settings, as per device specification.
+This is device dependent as not all the devices supports resolution
+setting, so it has been added in device family structures.
+
+The process to read the temperature on the device has been adapted in a
+new function 'convert_t()', which replace the former 'read_therm()', is
+introduce to deal with this timing. Strong pull up is also applied during
+the required time, according to device power status needs and
+'strong_pullup' module parameter.
+
+'temperature_from_RAM()' function is introduced to get the correct
+temperature computation (device dependent) from device RAM data.
+
+An new sysfs entry has been added to ouptut only temperature. The old
+entry w1_slave has been kept for compatibility, without changing its
+output format.
+
+Updating Documentation/ABI/testing/sysfs-driver-w1_therm accordingly.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203742.411039-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../ABI/testing/sysfs-driver-w1_therm         |  12 +
+ drivers/w1/slaves/w1_therm.c                  | 286 +++++++++++-------
+ 2 files changed, 197 insertions(+), 101 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-driver-w1_therm
++++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
+@@ -41,6 +41,18 @@ Users:              any user space application which
+               w1_term device
++What:         /sys/bus/w1/devices/.../temperature
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (RO) return the temperature in 1/1000 degC.
++              Note that the conversion duration depend on the resolution (if
++              device support this feature). It takes 94ms in 9bits
++              resolution, 750ms for 12bits.
++Users:                any user space application which wants to communicate with
++              w1_term device
++
++
+ What:         /sys/bus/w1/devices/.../w1_slave
+ Date:         May 2020
+ Contact:      Akira Shimahara <akira215corp@gmail.com>
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -93,6 +93,7 @@ module_param_named(strong_pullup, w1_str
+  * @reserved: not used here
+  * @f: pointer to the device binding structure
+  * @convert: pointer to the device conversion function
++ * @get_conversion_time: pointer to the device conversion time function
+  * @set_resolution: pointer to the device set_resolution function
+  * @get_resolution: pointer to the device get_resolution function
+  */
+@@ -101,6 +102,7 @@ struct w1_therm_family_converter {
+       u16             reserved;
+       struct w1_family        *f;
+       int             (*convert)(u8 rom[9]);
++      int             (*get_conversion_time)(struct w1_slave *sl);
+       int             (*set_resolution)(struct w1_slave *sl, int val);
+       int             (*get_resolution)(struct w1_slave *sl);
+ };
+@@ -154,6 +156,15 @@ struct therm_info {
+ static int reset_select_slave(struct w1_slave *sl);
+ /**
++ * convert_t() - Query the device for temperature conversion and read
++ * @sl: pointer to the slave to read
++ * @info: pointer to a structure to store the read results
++ *
++ * Return: 0 if success, -kernel error code otherwise
++ */
++static int convert_t(struct w1_slave *sl, struct therm_info *info);
++
++/**
+  * read_scratchpad() - read the data in device RAM
+  * @sl: pointer to the slave to read
+  * @info: pointer to a structure to store the read results
+@@ -213,6 +224,9 @@ static ssize_t w1_slave_store(struct dev
+ static ssize_t w1_seq_show(struct device *device,
+       struct device_attribute *attr, char *buf);
++static ssize_t temperature_show(struct device *device,
++      struct device_attribute *attr, char *buf);
++
+ static ssize_t ext_power_show(struct device *device,
+       struct device_attribute *attr, char *buf);
+@@ -229,6 +243,7 @@ static ssize_t eeprom_store(struct devic
+ static DEVICE_ATTR_RW(w1_slave);
+ static DEVICE_ATTR_RO(w1_seq);
++static DEVICE_ATTR_RO(temperature);
+ static DEVICE_ATTR_RO(ext_power);
+ static DEVICE_ATTR_RW(resolution);
+ static DEVICE_ATTR_WO(eeprom);
+@@ -259,6 +274,7 @@ static void w1_therm_remove_slave(struct
+ static struct attribute *w1_therm_attrs[] = {
+       &dev_attr_w1_slave.attr,
++      &dev_attr_temperature.attr,
+       &dev_attr_ext_power.attr,
+       &dev_attr_resolution.attr,
+       &dev_attr_eeprom.attr,
+@@ -267,6 +283,7 @@ static struct attribute *w1_therm_attrs[
+ static struct attribute *w1_ds18s20_attrs[] = {
+       &dev_attr_w1_slave.attr,
++      &dev_attr_temperature.attr,
+       &dev_attr_ext_power.attr,
+       &dev_attr_eeprom.attr,
+       NULL,
+@@ -275,6 +292,7 @@ static struct attribute *w1_ds18s20_attr
+ static struct attribute *w1_ds28ea00_attrs[] = {
+       &dev_attr_w1_slave.attr,
+       &dev_attr_w1_seq.attr,
++      &dev_attr_temperature.attr,
+       &dev_attr_ext_power.attr,
+       &dev_attr_resolution.attr,
+       &dev_attr_eeprom.attr,
+@@ -389,6 +407,37 @@ static struct w1_family w1_therm_family_
+ /* Device dependent func */
++static inline int w1_DS18B20_convert_time(struct w1_slave *sl)
++{
++      int ret;
++
++      if (!sl->family_data)
++              return -ENODEV; /* device unknown */
++
++      /* return time in ms for conversion operation */
++      switch (SLAVE_RESOLUTION(sl)) {
++      case 9:
++              ret = 95;
++              break;
++      case 10:
++              ret = 190;
++              break;
++      case 11:
++              ret = 375;
++              break;
++      case 12:
++      default:
++              ret = 750;
++      }
++      return ret;
++}
++
++static inline int w1_DS18S20_convert_time(struct w1_slave *sl)
++{
++      (void)(sl);
++      return 750; /* always 750ms for DS18S20 */
++}
++
+ static inline int w1_DS18B20_write_data(struct w1_slave *sl,
+                               const u8 *data)
+ {
+@@ -480,8 +529,10 @@ static inline int w1_DS18S20_convert_tem
+ {
+       int t, h;
+-      if (!rom[7])
++      if (!rom[7]) {
++              pr_debug("%s: Invalid argument for conversion\n", __func__);
+               return 0;
++      }
+       if (rom[1] == 0)
+               t = ((s32)rom[0] >> 1)*1000;
+@@ -500,34 +551,39 @@ static inline int w1_DS18S20_convert_tem
+ static struct w1_therm_family_converter w1_therm_families[] = {
+       {
+-              .f              = &w1_therm_family_DS18S20,
+-              .convert        = w1_DS18S20_convert_temp,
+-              .set_resolution = NULL, /* no config register */
+-              .get_resolution = NULL, /* no config register */
++              .f                              = &w1_therm_family_DS18S20,
++              .convert                        = w1_DS18S20_convert_temp,
++              .get_conversion_time    = w1_DS18S20_convert_time,
++              .set_resolution         = NULL, /* no config register */
++              .get_resolution         = NULL, /* no config register */
+       },
+       {
+-              .f              = &w1_therm_family_DS1822,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .set_resolution = w1_DS18B20_set_resolution,
+-              .get_resolution = w1_DS18B20_get_resolution,
++              .f                              = &w1_therm_family_DS1822,
++              .convert                        = w1_DS18B20_convert_temp,
++              .get_conversion_time    = w1_DS18B20_convert_time,
++              .set_resolution         = w1_DS18B20_set_resolution,
++              .get_resolution         = w1_DS18B20_get_resolution,
+       },
+       {
+-              .f              = &w1_therm_family_DS18B20,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .set_resolution = w1_DS18B20_set_resolution,
+-              .get_resolution = w1_DS18B20_get_resolution,
++              .f                              = &w1_therm_family_DS18B20,
++              .convert                        = w1_DS18B20_convert_temp,
++              .get_conversion_time    = w1_DS18B20_convert_time,
++              .set_resolution         = w1_DS18B20_set_resolution,
++              .get_resolution         = w1_DS18B20_get_resolution,
+       },
+       {
+-              .f              = &w1_therm_family_DS28EA00,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .set_resolution = w1_DS18B20_set_resolution,
+-              .get_resolution = w1_DS18B20_get_resolution,
++              .f                              = &w1_therm_family_DS28EA00,
++              .convert                        = w1_DS18B20_convert_temp,
++              .get_conversion_time    = w1_DS18B20_convert_time,
++              .set_resolution         = w1_DS18B20_set_resolution,
++              .get_resolution         = w1_DS18B20_get_resolution,
+       },
+       {
+-              .f              = &w1_therm_family_DS1825,
+-              .convert        = w1_DS18B20_convert_temp,
+-              .set_resolution = w1_DS18B20_set_resolution,
+-              .get_resolution = w1_DS18B20_get_resolution,
++              .f                              = &w1_therm_family_DS1825,
++              .convert                        = w1_DS18B20_convert_temp,
++              .get_conversion_time    = w1_DS18B20_convert_time,
++              .set_resolution         = w1_DS18B20_set_resolution,
++              .get_resolution         = w1_DS18B20_get_resolution,
+       }
+ };
+@@ -582,24 +638,44 @@ static inline bool bus_mutex_lock(struct
+ }
+ /**
+- * w1_convert_temp() - temperature conversion binding function
+- * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
+- * @fid: device family id
++ * conversion_time() - get the Tconv for the slave
++ * @sl: device to get the conversion time
+  *
+- * The function call the temperature computation function according to
+- * device family.
++ * On device supporting resolution settings, conversion time depend
++ * on the resolution setting. This helper function get the slave timing,
++ * depending on its current setting.
+  *
+- * Return: value in millidegrees Celsius.
++ * Return: conversion time in ms, negative values are kernel error code
+  */
+-static inline int w1_convert_temp(u8 rom[9], u8 fid)
++static inline int conversion_time(struct w1_slave *sl)
+ {
+-      int i;
++      if (SLAVE_SPECIFIC_FUNC(sl))
++              return SLAVE_SPECIFIC_FUNC(sl)->get_conversion_time(sl);
+-      for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
+-              if (w1_therm_families[i].f->fid == fid)
+-                      return w1_therm_families[i].convert(rom);
++      dev_info(&sl->dev,
++              "%s: Device not supported by the driver\n", __func__);
+-      return 0;
++      return -ENODEV;  /* No device family */
++}
++
++/**
++ * temperature_from_RAM() - Convert the read info to temperature
++ * @sl: device that sent the RAM data
++ * @rom: read value on the slave device RAM
++ *
++ * Device dependent, the function bind the correct computation method.
++ *
++ * Return: temperature in 1/1000degC, 0 on error.
++ */
++static inline int temperature_from_RAM(struct w1_slave *sl, u8 rom[9])
++{
++      if (SLAVE_SPECIFIC_FUNC(sl))
++              return SLAVE_SPECIFIC_FUNC(sl)->convert(rom);
++
++      dev_info(&sl->dev,
++              "%s: Device not supported by the driver\n", __func__);
++
++      return 0;  /* No device family */
+ }
+ /* Interface Functions */
+@@ -679,96 +755,74 @@ static int reset_select_slave(struct w1_
+       return 0;
+ }
+-static ssize_t read_therm(struct device *device,
+-                        struct w1_slave *sl, struct therm_info *info)
++static int convert_t(struct w1_slave *sl, struct therm_info *info)
+ {
+-      struct w1_master *dev = sl->master;
+-      u8 external_power;
+-      int ret, max_trying = 10;
+-      u8 *family_data = sl->family_data;
++      struct w1_master *dev_master = sl->master;
++      int max_trying = W1_THERM_MAX_TRY;
++      int t_conv;
++      int ret = -ENODEV;
++      bool strong_pullup;
+-      if (!family_data) {
+-              ret = -ENODEV;
++      if (!sl->family_data)
+               goto error;
+-      }
+-      /* prevent the slave from going away in sleep */
+-      atomic_inc(THERM_REFCNT(family_data));
++      strong_pullup = (w1_strong_pullup == 2 ||
++                                      (!SLAVE_POWERMODE(sl) &&
++                                      w1_strong_pullup));
+-      ret = mutex_lock_interruptible(&dev->bus_mutex);
+-      if (ret != 0)
+-              goto dec_refcnt;
++      /* get conversion duration device and id dependent */
++      t_conv = conversion_time(sl);
+       memset(info->rom, 0, sizeof(info->rom));
+-      while (max_trying--) {
++      /* prevent the slave from going away in sleep */
++      atomic_inc(THERM_REFCNT(sl->family_data));
++
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
++              goto dec_refcnt;
++      }
++
++      while (max_trying-- && ret) { /* ret should be 0 */
+               info->verdict = 0;
+               info->crc = 0;
+-
++              /* safe version to select slave */
+               if (!reset_select_slave(sl)) {
+-                      int count = 0;
+-                      unsigned int tm = 750;
+                       unsigned long sleep_rem;
+-                      w1_write_8(dev, W1_READ_PSUPPLY);
+-                      external_power = w1_read_8(dev);
+-
+-                      if (reset_select_slave(sl))
+-                              continue;
+-
+                       /* 750ms strong pullup (or delay) after the convert */
+-                      if (w1_strong_pullup == 2 ||
+-                                      (!external_power && w1_strong_pullup))
+-                              w1_next_pullup(dev, tm);
+-
+-                      w1_write_8(dev, W1_CONVERT_TEMP);
++                      if (strong_pullup)
++                              w1_next_pullup(dev_master, t_conv);
+-                      if (external_power) {
+-                              mutex_unlock(&dev->bus_mutex);
++                      w1_write_8(dev_master, W1_CONVERT_TEMP);
+-                              sleep_rem = msleep_interruptible(tm);
++                      if (strong_pullup) { /*some device need pullup */
++                              sleep_rem = msleep_interruptible(t_conv);
+                               if (sleep_rem != 0) {
+                                       ret = -EINTR;
+-                                      goto dec_refcnt;
++                                      goto mt_unlock;
+                               }
++                              mutex_unlock(&dev_master->bus_mutex);
++                      } else { /*no device need pullup */
++                              mutex_unlock(&dev_master->bus_mutex);
+-                              ret = mutex_lock_interruptible(&dev->bus_mutex);
+-                              if (ret != 0)
+-                                      goto dec_refcnt;
+-                      } else if (!w1_strong_pullup) {
+-                              sleep_rem = msleep_interruptible(tm);
++                              sleep_rem = msleep_interruptible(t_conv);
+                               if (sleep_rem != 0) {
+                                       ret = -EINTR;
+-                                      goto mt_unlock;
++                                      goto dec_refcnt;
+                               }
+                       }
+-
+-                      if (!reset_select_slave(sl)) {
+-
+-                              w1_write_8(dev, W1_READ_SCRATCHPAD);
+-                              count = w1_read_block(dev, info->rom, 9);
+-                              if (count != 9) {
+-                                      dev_warn(device, "w1_read_block() "
+-                                              "returned %u instead of 9.\n",
+-                                              count);
+-                              }
+-
+-                              info->crc = w1_calc_crc8(info->rom, 8);
+-
+-                              if (info->rom[8] == info->crc)
+-                                      info->verdict = 1;
+-                      }
++                      ret = read_scratchpad(sl, info);
++                      goto dec_refcnt;
+               }
+-              if (info->verdict)
+-                      break;
+       }
+ mt_unlock:
+-      mutex_unlock(&dev->bus_mutex);
++      mutex_unlock(&dev_master->bus_mutex);
+ dec_refcnt:
+-      atomic_dec(THERM_REFCNT(family_data));
++      atomic_dec(THERM_REFCNT(sl->family_data));
+ error:
+       return ret;
+ }
+@@ -1000,27 +1054,33 @@ static ssize_t w1_slave_show(struct devi
+       u8 *family_data = sl->family_data;
+       int ret, i;
+       ssize_t c = PAGE_SIZE;
+-      u8 fid = sl->family->fid;
+-      ret = read_therm(device, sl, &info);
+-      if (ret)
+-              return ret;
++      ret = convert_t(sl, &info);
++
++      if (ret < 0) {
++              dev_dbg(device,
++                      "%s: Temperature data may be corrupted. err=%d\n",
++                      __func__, ret);
++              return 0;
++      }
+       for (i = 0; i < 9; ++i)
+               c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", info.rom[i]);
+       c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
+                     info.crc, (info.verdict) ? "YES" : "NO");
++
+       if (info.verdict)
+               memcpy(family_data, info.rom, sizeof(info.rom));
+       else
+-              dev_warn(device, "Read failed CRC check\n");
++              dev_warn(device, "%s:Read failed CRC check\n", __func__);
+       for (i = 0; i < 9; ++i)
+               c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ",
+                             ((u8 *)family_data)[i]);
+       c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
+-                      w1_convert_temp(info.rom, fid));
++                      temperature_from_RAM(sl, info.rom));
++
+       ret = PAGE_SIZE - c;
+       return ret;
+ }
+@@ -1063,6 +1123,31 @@ static ssize_t w1_slave_store(struct dev
+       return size; /* always return size to avoid infinite calling */
+ }
++static ssize_t temperature_show(struct device *device,
++      struct device_attribute *attr, char *buf)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      struct therm_info info;
++      int ret = 0;
++
++      if ((!sl->family_data) || (!SLAVE_SPECIFIC_FUNC(sl))) {
++              dev_info(device,
++                      "%s: Device not supported by the driver\n", __func__);
++              return 0;  /* No device family */
++      }
++
++      ret = convert_t(sl, &info);
++
++      if (ret < 0) {
++              dev_dbg(device,
++                      "%s: Temperature data may be corrupted. err=%d\n",
++                      __func__, ret);
++              return 0;
++      }
++
++      return sprintf(buf, "%d\n", temperature_from_RAM(sl, info.rom));
++}
++
+ static ssize_t ext_power_show(struct device *device,
+       struct device_attribute *attr, char *buf)
+ {
+@@ -1172,12 +1257,11 @@ static int w1_read_temp(struct device *d
+ {
+       struct w1_slave *sl = dev_get_drvdata(device);
+       struct therm_info info;
+-      u8 fid = sl->family->fid;
+       int ret;
+       switch (attr) {
+       case hwmon_temp_input:
+-              ret = read_therm(device, sl, &info);
++              ret = convert_t(sl, &info);
+               if (ret)
+                       return ret;
+@@ -1186,7 +1270,7 @@ static int w1_read_temp(struct device *d
+                       return ret;
+               }
+-              *val = w1_convert_temp(info.rom, fid);
++              *val = temperature_from_RAM(sl, info.rom);
+               ret = 0;
+               break;
+       default:
diff --git a/target/linux/bcm27xx/patches-5.4/950-0772-w1_therm-adding-alarm-sysfs-entry.patch b/target/linux/bcm27xx/patches-5.4/950-0772-w1_therm-adding-alarm-sysfs-entry.patch
new file mode 100644 (file)
index 0000000..f4b8d5d
--- /dev/null
@@ -0,0 +1,319 @@
+From 8c3d9356c3c3b9c9188f1e192c7e2541e313c7ab Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:38:01 +0200
+Subject: [PATCH] w1_therm: adding alarm sysfs entry
+
+commit e2c94d6f572079511945e64537eb1218643f2e68 upstream.
+
+Adding device alarms settings by a dedicated sysfs entry alarms (RW):
+read or write TH and TL in the device RAM. Checking devices in alarm
+state could be performed using the master search command.
+
+As alarms temperature level are store in a 8 bit register on the device
+and are signed values, a safe cast shall be performed using the min and
+max temperature that device are able to measure. This is done by
+int_to_short inline function.
+
+A 'write_data' field is added in the device structure, to bind the
+correct writing function, as some devices may have 2 or 3 bytes RAM.
+
+Updating Documentation/ABI/testing/sysfs-driver-w1_therm accordingly.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203801.411253-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../ABI/testing/sysfs-driver-w1_therm         |  16 ++
+ drivers/w1/slaves/w1_therm.c                  | 161 ++++++++++++++++++
+ 2 files changed, 177 insertions(+)
+
+--- a/Documentation/ABI/testing/sysfs-driver-w1_therm
++++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
+@@ -1,3 +1,19 @@
++What:         /sys/bus/w1/devices/.../alarms
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (RW) read or write TH and TL (Temperature High an Low) alarms.
++              Values shall be space separated and in the device range
++              (typical -55 degC to 125 degC), if not values will be trimmed
++              to device min/max capabilities. Values are integer as they are
++              stored in a 8bit register in the device. Lowest value is
++              automatically put to TL. Once set, alarms could be search at
++              master level, refer to Documentation/w1/w1_generic.rst for
++              detailed information
++Users:                any user space application which wants to communicate with
++              w1_term device
++
++
+ What:         /sys/bus/w1/devices/.../eeprom
+ Date:         May 2020
+ Contact:      Akira Shimahara <akira215corp@gmail.com>
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -58,6 +58,9 @@ module_param_named(strong_pullup, w1_str
+ #define EEPROM_CMD_WRITE    "save"    /* cmd for write eeprom sysfs */
+ #define EEPROM_CMD_READ     "restore" /* cmd for read eeprom sysfs */
++#define MIN_TEMP      -55     /* min temperature that can be mesured */
++#define MAX_TEMP      125     /* max temperature that can be mesured */
++
+ /* Helpers Macros */
+ /*
+@@ -96,6 +99,7 @@ module_param_named(strong_pullup, w1_str
+  * @get_conversion_time: pointer to the device conversion time function
+  * @set_resolution: pointer to the device set_resolution function
+  * @get_resolution: pointer to the device get_resolution function
++ * @write_data: pointer to the device writing function (2 or 3 bytes)
+  */
+ struct w1_therm_family_converter {
+       u8              broken;
+@@ -105,6 +109,7 @@ struct w1_therm_family_converter {
+       int             (*get_conversion_time)(struct w1_slave *sl);
+       int             (*set_resolution)(struct w1_slave *sl, int val);
+       int             (*get_resolution)(struct w1_slave *sl);
++      int             (*write_data)(struct w1_slave *sl, const u8 *data);
+ };
+ /**
+@@ -239,6 +244,12 @@ static ssize_t resolution_store(struct d
+ static ssize_t eeprom_store(struct device *device,
+       struct device_attribute *attr, const char *buf, size_t size);
++static ssize_t alarms_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size);
++
++static ssize_t alarms_show(struct device *device,
++      struct device_attribute *attr, char *buf);
++
+ /* Attributes declarations */
+ static DEVICE_ATTR_RW(w1_slave);
+@@ -247,6 +258,7 @@ static DEVICE_ATTR_RO(temperature);
+ static DEVICE_ATTR_RO(ext_power);
+ static DEVICE_ATTR_RW(resolution);
+ static DEVICE_ATTR_WO(eeprom);
++static DEVICE_ATTR_RW(alarms);
+ /* Interface Functions declaration */
+@@ -278,6 +290,7 @@ static struct attribute *w1_therm_attrs[
+       &dev_attr_ext_power.attr,
+       &dev_attr_resolution.attr,
+       &dev_attr_eeprom.attr,
++      &dev_attr_alarms.attr,
+       NULL,
+ };
+@@ -286,6 +299,7 @@ static struct attribute *w1_ds18s20_attr
+       &dev_attr_temperature.attr,
+       &dev_attr_ext_power.attr,
+       &dev_attr_eeprom.attr,
++      &dev_attr_alarms.attr,
+       NULL,
+ };
+@@ -296,6 +310,7 @@ static struct attribute *w1_ds28ea00_att
+       &dev_attr_ext_power.attr,
+       &dev_attr_resolution.attr,
+       &dev_attr_eeprom.attr,
++      &dev_attr_alarms.attr,
+       NULL,
+ };
+@@ -556,6 +571,7 @@ static struct w1_therm_family_converter
+               .get_conversion_time    = w1_DS18S20_convert_time,
+               .set_resolution         = NULL, /* no config register */
+               .get_resolution         = NULL, /* no config register */
++              .write_data                     = w1_DS18S20_write_data,
+       },
+       {
+               .f                              = &w1_therm_family_DS1822,
+@@ -563,6 +579,7 @@ static struct w1_therm_family_converter
+               .get_conversion_time    = w1_DS18B20_convert_time,
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
++              .write_data                     = w1_DS18B20_write_data,
+       },
+       {
+               .f                              = &w1_therm_family_DS18B20,
+@@ -570,6 +587,7 @@ static struct w1_therm_family_converter
+               .get_conversion_time    = w1_DS18B20_convert_time,
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
++              .write_data                     = w1_DS18B20_write_data,
+       },
+       {
+               .f                              = &w1_therm_family_DS28EA00,
+@@ -577,6 +595,7 @@ static struct w1_therm_family_converter
+               .get_conversion_time    = w1_DS18B20_convert_time,
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
++              .write_data                     = w1_DS18B20_write_data,
+       },
+       {
+               .f                              = &w1_therm_family_DS1825,
+@@ -584,6 +603,7 @@ static struct w1_therm_family_converter
+               .get_conversion_time    = w1_DS18B20_convert_time,
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
++              .write_data                     = w1_DS18B20_write_data,
+       }
+ };
+@@ -678,6 +698,26 @@ static inline int temperature_from_RAM(s
+       return 0;  /* No device family */
+ }
++/**
++ * int_to_short() - Safe casting of int to short
++ *
++ * @i: integer to be converted to short
++ *
++ * Device register use 1 byte to store signed integer.
++ * This helper function convert the int in a signed short,
++ * using the min/max values that device can measure as limits.
++ * min/max values are defined by macro.
++ *
++ * Return: a short in the range of min/max value
++ */
++static inline s8 int_to_short(int i)
++{
++      /* Prepare to cast to short by eliminating out of range values */
++      i = i > MAX_TEMP ? MAX_TEMP : i;
++      i = i < MIN_TEMP ? MIN_TEMP : i;
++      return (s8) i;
++}
++
+ /* Interface Functions */
+ static int w1_therm_add_slave(struct w1_slave *sl)
+@@ -1250,6 +1290,127 @@ static ssize_t eeprom_store(struct devic
+       return size;
+ }
++
++static ssize_t alarms_show(struct device *device,
++      struct device_attribute *attr, char *buf)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      int ret = -ENODEV;
++      s8 th = 0, tl = 0;
++      struct therm_info scratchpad;
++
++      ret = read_scratchpad(sl, &scratchpad);
++
++      if (!ret)       {
++              th = scratchpad.rom[2]; /* TH is byte 2 */
++              tl = scratchpad.rom[3]; /* TL is byte 3 */
++      } else {
++              dev_info(device,
++                      "%s: error reading alarms register %d\n",
++                      __func__, ret);
++      }
++
++      return sprintf(buf, "%hd %hd\n", tl, th);
++}
++
++static ssize_t alarms_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size)
++{
++      struct w1_slave *sl = dev_to_w1_slave(device);
++      struct therm_info info;
++      u8 new_config_register[3];      /* array of data to be written */
++      int temp, ret = -EINVAL;
++      char *token = NULL;
++      s8 tl, th, tt;  /* 1 byte per value + temp ring order */
++      char *p_args = kmalloc(size, GFP_KERNEL);
++
++      /* Safe string copys as buf is const */
++      if (!p_args) {
++              dev_warn(device,
++                      "%s: error unable to allocate memory %d\n",
++                      __func__, -ENOMEM);
++              return size;
++      }
++      strcpy(p_args, buf);
++
++      /* Split string using space char */
++      token = strsep(&p_args, " ");
++
++      if (!token)     {
++              dev_info(device,
++                      "%s: error parsing args %d\n", __func__, -EINVAL);
++              goto free_m;
++      }
++
++      /* Convert 1st entry to int */
++      ret = kstrtoint (token, 10, &temp);
++      if (ret) {
++              dev_info(device,
++                      "%s: error parsing args %d\n", __func__, ret);
++              goto free_m;
++      }
++
++      tl = int_to_short(temp);
++
++      /* Split string using space char */
++      token = strsep(&p_args, " ");
++      if (!token)     {
++              dev_info(device,
++                      "%s: error parsing args %d\n", __func__, -EINVAL);
++              goto free_m;
++      }
++      /* Convert 2nd entry to int */
++      ret = kstrtoint (token, 10, &temp);
++      if (ret) {
++              dev_info(device,
++                      "%s: error parsing args %d\n", __func__, ret);
++              goto free_m;
++      }
++
++      /* Prepare to cast to short by eliminating out of range values */
++      th = int_to_short(temp);
++
++      /* Reorder if required th and tl */
++      if (tl > th) {
++              tt = tl; tl = th; th = tt;
++      }
++
++      /*
++       * Read the scratchpad to change only the required bits
++       * (th : byte 2 - tl: byte 3)
++       */
++      ret = read_scratchpad(sl, &info);
++      if (!ret) {
++              new_config_register[0] = th;    /* Byte 2 */
++              new_config_register[1] = tl;    /* Byte 3 */
++              new_config_register[2] = info.rom[4];/* Byte 4 */
++      } else {
++              dev_info(device,
++                      "%s: error reading from the slave device %d\n",
++                      __func__, ret);
++              goto free_m;
++      }
++
++      /* Write data in the device RAM */
++      if (!SLAVE_SPECIFIC_FUNC(sl)) {
++              dev_info(device,
++                      "%s: Device not supported by the driver %d\n",
++                      __func__, -ENODEV);
++              goto free_m;
++      }
++
++      ret = SLAVE_SPECIFIC_FUNC(sl)->write_data(sl, new_config_register);
++      if (ret)
++              dev_info(device,
++                      "%s: error writing to the slave device %d\n",
++                      __func__, ret);
++
++free_m:
++      /* free allocated memory */
++      kfree(p_args);
++
++      return size;
++}
+ #if IS_REACHABLE(CONFIG_HWMON)
+ static int w1_read_temp(struct device *device, u32 attr, int channel,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch b/target/linux/bcm27xx/patches-5.4/950-0773-w1_therm-adding-bulk-read-support-to-trigger-multipl.patch
new file mode 100644 (file)
index 0000000..ad641e1
--- /dev/null
@@ -0,0 +1,587 @@
+From e6585a1d299375740f95f30027b8b3f4b34e7548 Mon Sep 17 00:00:00 2001
+From: Akira Shimahara <akira215corp@gmail.com>
+Date: Mon, 11 May 2020 22:38:20 +0200
+Subject: [PATCH] w1_therm: adding bulk read support to trigger
+ multiple conversion on bus
+
+commit 57c76221d5af648c8355a55c09b050c5d8d38189 upstream.
+
+Adding bulk read support:
+Sending a 'trigger' command in the dedicated sysfs entry of bus master
+device send a conversion command for all the slaves on the bus. The sysfs
+entry is added as soon as at least one device supporting this feature
+is detected on the bus.
+
+The behavior of the sysfs reading temperature on the device is as follow:
+ * If no bulk read pending, trigger a conversion on the device, wait for
+ the conversion to be done, read the temperature in device RAM
+ * If a bulk read has been trigger, access directly the device RAM
+This behavior is the same on the 2 sysfs entries ('temperature' and
+'w1_slave').
+
+Reading the therm_bulk_read sysfs give the status of bulk operations:
+ * '-1': conversion in progress on at least 1 sensor
+ * '1': conversion complete but at least one sensor has not been read yet
+ * '0': no bulk operation. Reading temperature on ecah device will trigger
+a conversion
+
+As not all devices support bulk read feature, it has been added in device
+family structure.
+
+The attribute is set at master level as soon as a supporting device is
+discover. It is removed when the last supported device leave the bus.
+The count of supported device is kept with the static counter
+bulk_read_device_counter.
+
+A strong pull up is apply on the line if at least one device required it.
+The duration of the pull up is the max time required by a device on the
+line, which depends on the resolution settings of each device. The strong
+pull up could be adjust with the a module parameter.
+
+Updating documentation in Documentation/ABI/testing/sysfs-driver-w1_therm
+and Documentation/w1/slaves/w1_therm.rst accordingly.
+
+Signed-off-by: Akira Shimahara <akira215corp@gmail.com>
+Link: https://lore.kernel.org/r/20200511203820.411483-1-akira215corp@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../ABI/testing/sysfs-driver-w1_therm         |  36 ++-
+ Documentation/w1/slaves/w1_therm.rst          |  50 +++-
+ drivers/w1/slaves/w1_therm.c                  | 251 +++++++++++++++++-
+ 3 files changed, 322 insertions(+), 15 deletions(-)
+
+--- a/Documentation/ABI/testing/sysfs-driver-w1_therm
++++ b/Documentation/ABI/testing/sysfs-driver-w1_therm
+@@ -62,9 +62,16 @@ Date:               May 2020
+ Contact:      Akira Shimahara <akira215corp@gmail.com>
+ Description:
+               (RO) return the temperature in 1/1000 degC.
+-              Note that the conversion duration depend on the resolution (if
+-              device support this feature). It takes 94ms in 9bits
+-              resolution, 750ms for 12bits.
++                      * If a bulk read has been triggered, it will directly
++                      return the temperature computed when the bulk read
++                      occurred, if available. If not yet available, nothing
++                      is returned (a debug kernel message is sent), you
++                      should retry later on.
++                      * If no bulk read has been triggered, it will trigger
++                      a conversion and send the result. Note that the
++                      conversion duration depend on the resolution (if
++                      device support this feature). It takes 94ms in 9bits
++                      resolution, 750ms for 12bits.
+ Users:                any user space application which wants to communicate with
+               w1_term device
+@@ -85,4 +92,25 @@ Description:
+               refer to Documentation/w1/slaves/w1_therm.rst for detailed
+               information.
+ Users:                any user space application which wants to communicate with
+-              w1_term device
+\ No newline at end of file
++              w1_term device
++
++
++What:         /sys/bus/w1/devices/w1_bus_masterXX/therm_bulk_read
++Date:         May 2020
++Contact:      Akira Shimahara <akira215corp@gmail.com>
++Description:
++              (RW) trigger a bulk read conversion. read the status
++              *read*:
++                      * '-1': conversion in progress on at least 1 sensor
++                      * '1' : conversion complete but at least one sensor
++                              value has not been read yet
++                      * '0' : no bulk operation. Reading temperature will
++                              trigger a conversion on each device
++              *write*: 'trigger': trigger a bulk read on all supporting
++                      devices on the bus
++              Note that if a bulk read is sent but one sensor is not read
++              immediately, the next access to temperature on this device
++              will return the temperature measured at the time of issue
++              of the bulk read command (not the current temperature).
++Users:                any user space application which wants to communicate with
++              w1_term device
+--- a/Documentation/w1/slaves/w1_therm.rst
++++ b/Documentation/w1/slaves/w1_therm.rst
+@@ -26,20 +26,31 @@ W1_THERM_DS1825            0x3B
+ W1_THERM_DS28EA00     0x42
+ ====================  ====
+-Support is provided through the sysfs w1_slave file.  Each open and
++Support is provided through the sysfs w1_slave file. Each open and
+ read sequence will initiate a temperature conversion then provide two
+-lines of ASCII output.  The first line contains the nine hex bytes
++lines of ASCII output. The first line contains the nine hex bytes
+ read along with a calculated crc value and YES or NO if it matched.
+-If the crc matched the returned values are retained.  The second line
++If the crc matched the returned values are retained. The second line
+ displays the retained values along with a temperature in millidegrees
+ Centigrade after t=.
+-Parasite powered devices are limited to one slave performing a
+-temperature conversion at a time.  If none of the devices are parasite
+-powered it would be possible to convert all the devices at the same
+-time and then go back to read individual sensors.  That isn't
+-currently supported.  The driver also doesn't support reduced
+-precision (which would also reduce the conversion time) when reading values.
++Alternatively, temperature can be read using temperature sysfs, it
++return only temperature in millidegrees Centigrade.
++
++A bulk read of all devices on the bus could be done writing 'trigger'
++in the therm_bulk_read sysfs entry at w1_bus_master level. This will
++sent the convert command on all devices on the bus, and if parasite
++powered devices are detected on the bus (and strong pullup is enable
++in the module), it will drive the line high during the longer conversion
++time required by parasited powered device on the line. Reading
++therm_bulk_read will return 0 if no bulk conversion pending,
++-1 if at least one sensor still in conversion, 1 if conversion is complete
++but at least one sensor value has not been read yet. Result temperature is
++then accessed by reading the temperature sysfs entry of each device, which
++may return empty if conversion is still in progress. Note that if a bulk
++read is sent but one sensor is not read immediately, the next access to
++temperature on this device will return the temperature measured at the
++time of issue of the bulk read command (not the current temperature).
+ Writing a value between 9 and 12 to the sysfs w1_slave file will change the
+ precision of the sensor for the next readings. This value is in (volatile)
+@@ -49,6 +60,27 @@ To store the current precision configura
+ has to be written to the sysfs w1_slave file. Since the EEPROM has a limited
+ amount of writes (>50k), this command should be used wisely.
++Alternatively, resolution can be set or read (value from 9 to 12) using the
++dedicated resolution sysfs entry on each device. This sysfs entry is not
++present for devices not supporting this feature. Driver will adjust the
++correct conversion time for each device regarding to its resolution setting.
++In particular, strong pullup will be applied if required during the conversion
++duration.
++
++The write-only sysfs entry eeprom is an alternative for EEPROM operations:
++  * 'save': will save device RAM to EEPROM
++  * 'restore': will restore EEPROM data in device RAM.
++
++ext_power syfs entry allow tho check the power status of each device.
++  * '0': device parasite powered
++  * '1': device externally powered
++
++sysfs alarms allow read or write TH and TL (Temperature High an Low) alarms.
++Values shall be space separated and in the device range (typical -55 degC
++to 125 degC). Values are integer as they are store in a 8bit register in
++the device. Lowest value is automatically put to TL.Once set, alarms could
++be search at master level.
++
+ The module parameter strong_pullup can be set to 0 to disable the
+ strong pullup, 1 to enable autodetection or 2 to force strong pullup.
+ In case of autodetection, the driver will use the "READ POWER SUPPLY"
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -43,6 +43,9 @@
+ static int w1_strong_pullup = 1;
+ module_param_named(strong_pullup, w1_strong_pullup, int, 0);
++/* Counter for devices supporting bulk reading */
++static u16 bulk_read_device_counter; /* =0 as per C standard */
++
+ /* This command should be in public header w1.h but is not */
+ #define W1_RECALL_EEPROM      0xB8
+@@ -57,6 +60,7 @@ module_param_named(strong_pullup, w1_str
+ #define EEPROM_CMD_WRITE    "save"    /* cmd for write eeprom sysfs */
+ #define EEPROM_CMD_READ     "restore" /* cmd for read eeprom sysfs */
++#define BULK_TRIGGER_CMD    "trigger" /* cmd to trigger a bulk read */
+ #define MIN_TEMP      -55     /* min temperature that can be mesured */
+ #define MAX_TEMP      125     /* max temperature that can be mesured */
+@@ -84,6 +88,15 @@ module_param_named(strong_pullup, w1_str
+ #define SLAVE_RESOLUTION(sl) \
+       (((struct w1_therm_family_data *)(sl->family_data))->resolution)
++/*
++ * return whether or not a converT command has been issued to the slave
++ * * 0: no bulk read is pending
++ * * -1: conversion is in progress
++ * * 1: conversion done, result to be read
++ */
++#define SLAVE_CONVERT_TRIGGERED(sl) \
++      (((struct w1_therm_family_data *)(sl->family_data))->convert_triggered)
++
+ /* return the address of the refcnt in the family data */
+ #define THERM_REFCNT(family_data) \
+       (&((struct w1_therm_family_data *)family_data)->refcnt)
+@@ -100,6 +113,7 @@ module_param_named(strong_pullup, w1_str
+  * @set_resolution: pointer to the device set_resolution function
+  * @get_resolution: pointer to the device get_resolution function
+  * @write_data: pointer to the device writing function (2 or 3 bytes)
++ * @bulk_read: true if device family support bulk read, false otherwise
+  */
+ struct w1_therm_family_converter {
+       u8              broken;
+@@ -110,6 +124,7 @@ struct w1_therm_family_converter {
+       int             (*set_resolution)(struct w1_slave *sl, int val);
+       int             (*get_resolution)(struct w1_slave *sl);
+       int             (*write_data)(struct w1_slave *sl, const u8 *data);
++      bool            bulk_read;
+ };
+ /**
+@@ -120,6 +135,7 @@ struct w1_therm_family_converter {
+  *                            0 device parasite powered,
+  *                            -x error or undefined
+  * @resolution: current device resolution
++ * @convert_triggered: conversion state of the device
+  * @specific_functions: pointer to struct of device specific function
+  */
+ struct w1_therm_family_data {
+@@ -127,6 +143,7 @@ struct w1_therm_family_data {
+       atomic_t refcnt;
+       int external_powered;
+       int resolution;
++      int convert_triggered;
+       struct w1_therm_family_converter *specific_functions;
+ };
+@@ -218,6 +235,18 @@ static int recall_eeprom(struct w1_slave
+  */
+ static int read_powermode(struct w1_slave *sl);
++/**
++ * trigger_bulk_read() - function to trigger a bulk read on the bus
++ * @dev_master: the device master of the bus
++ *
++ * Send a SKIP ROM follow by a CONVERT T commmand on the bus.
++ * It also set the status flag in each slave &struct w1_therm_family_data
++ * to signal that a conversion is in progress.
++ *
++ * Return: 0 if success, -kernel error code otherwise
++ */
++static int trigger_bulk_read(struct w1_master *dev_master);
++
+ /* Sysfs interface declaration */
+ static ssize_t w1_slave_show(struct device *device,
+@@ -250,6 +279,12 @@ static ssize_t alarms_store(struct devic
+ static ssize_t alarms_show(struct device *device,
+       struct device_attribute *attr, char *buf);
++static ssize_t therm_bulk_read_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size);
++
++static ssize_t therm_bulk_read_show(struct device *device,
++      struct device_attribute *attr, char *buf);
++
+ /* Attributes declarations */
+ static DEVICE_ATTR_RW(w1_slave);
+@@ -260,6 +295,8 @@ static DEVICE_ATTR_RW(resolution);
+ static DEVICE_ATTR_WO(eeprom);
+ static DEVICE_ATTR_RW(alarms);
++static DEVICE_ATTR_RW(therm_bulk_read); /* attribut at master level */
++
+ /* Interface Functions declaration */
+ /**
+@@ -572,6 +609,7 @@ static struct w1_therm_family_converter
+               .set_resolution         = NULL, /* no config register */
+               .get_resolution         = NULL, /* no config register */
+               .write_data                     = w1_DS18S20_write_data,
++              .bulk_read                      = true
+       },
+       {
+               .f                              = &w1_therm_family_DS1822,
+@@ -580,6 +618,7 @@ static struct w1_therm_family_converter
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
+               .write_data                     = w1_DS18B20_write_data,
++              .bulk_read                      = true
+       },
+       {
+               .f                              = &w1_therm_family_DS18B20,
+@@ -588,6 +627,7 @@ static struct w1_therm_family_converter
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
+               .write_data                     = w1_DS18B20_write_data,
++              .bulk_read                      = true
+       },
+       {
+               .f                              = &w1_therm_family_DS28EA00,
+@@ -596,6 +636,7 @@ static struct w1_therm_family_converter
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
+               .write_data                     = w1_DS18B20_write_data,
++              .bulk_read                      = false
+       },
+       {
+               .f                              = &w1_therm_family_DS1825,
+@@ -604,6 +645,7 @@ static struct w1_therm_family_converter
+               .set_resolution         = w1_DS18B20_set_resolution,
+               .get_resolution         = w1_DS18B20_get_resolution,
+               .write_data                     = w1_DS18B20_write_data,
++              .bulk_read                      = true
+       }
+ };
+@@ -658,6 +700,23 @@ static inline bool bus_mutex_lock(struct
+ }
+ /**
++ * support_bulk_read() - check if slave support bulk read
++ * @sl: device to check the ability
++ *
++ * Return: true if bulk read is supported, false if not or error
++ */
++static inline bool bulk_read_support(struct w1_slave *sl)
++{
++      if (SLAVE_SPECIFIC_FUNC(sl))
++              return SLAVE_SPECIFIC_FUNC(sl)->bulk_read;
++
++      dev_info(&sl->dev,
++              "%s: Device not supported by the driver\n", __func__);
++
++      return false;  /* No device family */
++}
++
++/**
+  * conversion_time() - get the Tconv for the slave
+  * @sl: device to get the conversion time
+  *
+@@ -741,6 +800,24 @@ static int w1_therm_add_slave(struct w1_
+       /* save this pointer to the device structure */
+       SLAVE_SPECIFIC_FUNC(sl) = sl_family_conv;
++      if (bulk_read_support(sl)) {
++              /*
++               * add the sys entry to trigger bulk_read
++               * at master level only the 1st time
++               */
++              if (!bulk_read_device_counter) {
++                      int err = device_create_file(&sl->master->dev,
++                              &dev_attr_therm_bulk_read);
++
++                      if (err)
++                              dev_warn(&sl->dev,
++                              "%s: Device has been added, but bulk read is unavailable. err=%d\n",
++                              __func__, err);
++              }
++              /* Increment the counter */
++              bulk_read_device_counter++;
++      }
++
+       /* Getting the power mode of the device {external, parasite} */
+       SLAVE_POWERMODE(sl) = read_powermode(sl);
+@@ -763,6 +840,9 @@ static int w1_therm_add_slave(struct w1_
+               }
+       }
++      /* Finally initialize convert_triggered flag */
++      SLAVE_CONVERT_TRIGGERED(sl) = 0;
++
+       return 0;
+ }
+@@ -770,6 +850,14 @@ static void w1_therm_remove_slave(struct
+ {
+       int refcnt = atomic_sub_return(1, THERM_REFCNT(sl->family_data));
++      if (bulk_read_support(sl)) {
++              bulk_read_device_counter--;
++              /* Delete the entry if no more device support the feature */
++              if (!bulk_read_device_counter)
++                      device_remove_file(&sl->master->dev,
++                              &dev_attr_therm_bulk_read);
++      }
++
+       while (refcnt) {
+               msleep(1000);
+               refcnt = atomic_read(THERM_REFCNT(sl->family_data));
+@@ -1084,6 +1172,96 @@ error:
+       return ret;
+ }
++static int trigger_bulk_read(struct w1_master *dev_master)
++{
++      struct w1_slave *sl = NULL; /* used to iterate through slaves */
++      int max_trying = W1_THERM_MAX_TRY;
++      int t_conv = 0;
++      int ret = -ENODEV;
++      bool strong_pullup = false;
++
++      /*
++       * Check whether there are parasite powered device on the bus,
++       * and compute duration of conversion for these devices
++       * so we can apply a strong pullup if required
++       */
++      list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
++              if (!sl->family_data)
++                      goto error;
++              if (bulk_read_support(sl)) {
++                      int t_cur = conversion_time(sl);
++
++                      t_conv = t_cur > t_conv ? t_cur : t_conv;
++                      strong_pullup = strong_pullup ||
++                                      (w1_strong_pullup == 2 ||
++                                      (!SLAVE_POWERMODE(sl) &&
++                                      w1_strong_pullup));
++              }
++      }
++
++      /*
++       * t_conv is the max conversion time required on the bus
++       * If its 0, no device support the bulk read feature
++       */
++      if (!t_conv)
++              goto error;
++
++      if (!bus_mutex_lock(&dev_master->bus_mutex)) {
++              ret = -EAGAIN;  /* Didn't acquire the mutex */
++              goto error;
++      }
++
++      while ((max_trying--) && (ret < 0)) { /* ret should be either 0 */
++
++              if (!w1_reset_bus(dev_master)) {        /* Just reset the bus */
++                      unsigned long sleep_rem;
++
++                      w1_write_8(dev_master, W1_SKIP_ROM);
++
++                      if (strong_pullup)      /* Apply pullup if required */
++                              w1_next_pullup(dev_master, t_conv);
++
++                      w1_write_8(dev_master, W1_CONVERT_TEMP);
++
++                      /* set a flag to instruct that converT pending */
++                      list_for_each_entry(sl,
++                              &dev_master->slist, w1_slave_entry) {
++                              if (bulk_read_support(sl))
++                                      SLAVE_CONVERT_TRIGGERED(sl) = -1;
++                      }
++
++                      if (strong_pullup) { /* some device need pullup */
++                              sleep_rem = msleep_interruptible(t_conv);
++                              if (sleep_rem != 0) {
++                                      ret = -EINTR;
++                                      goto mt_unlock;
++                              }
++                              mutex_unlock(&dev_master->bus_mutex);
++                      } else {
++                              mutex_unlock(&dev_master->bus_mutex);
++                              sleep_rem = msleep_interruptible(t_conv);
++                              if (sleep_rem != 0) {
++                                      ret = -EINTR;
++                                      goto set_flag;
++                              }
++                      }
++                      ret = 0;
++                      goto set_flag;
++              }
++      }
++
++mt_unlock:
++      mutex_unlock(&dev_master->bus_mutex);
++set_flag:
++      /* set a flag to register convsersion is done */
++      list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
++              if (bulk_read_support(sl))
++                      SLAVE_CONVERT_TRIGGERED(sl) = 1;
++      }
++error:
++      return ret;
++}
++
+ /* Sysfs Interface definition */
+ static ssize_t w1_slave_show(struct device *device,
+@@ -1095,7 +1273,20 @@ static ssize_t w1_slave_show(struct devi
+       int ret, i;
+       ssize_t c = PAGE_SIZE;
+-      ret = convert_t(sl, &info);
++      if (bulk_read_support(sl)) {
++              if (SLAVE_CONVERT_TRIGGERED(sl) < 0) {
++                      dev_dbg(device,
++                              "%s: Conversion in progress, retry later\n",
++                              __func__);
++                      return 0;
++              } else if (SLAVE_CONVERT_TRIGGERED(sl) > 0) {
++                      /* A bulk read has been issued, read the device RAM */
++                      ret = read_scratchpad(sl, &info);
++                      SLAVE_CONVERT_TRIGGERED(sl) = 0;
++              } else
++                      ret = convert_t(sl, &info);
++      } else
++              ret = convert_t(sl, &info);
+       if (ret < 0) {
+               dev_dbg(device,
+@@ -1176,7 +1367,20 @@ static ssize_t temperature_show(struct d
+               return 0;  /* No device family */
+       }
+-      ret = convert_t(sl, &info);
++      if (bulk_read_support(sl)) {
++              if (SLAVE_CONVERT_TRIGGERED(sl) < 0) {
++                      dev_dbg(device,
++                              "%s: Conversion in progress, retry later\n",
++                              __func__);
++                      return 0;
++              } else if (SLAVE_CONVERT_TRIGGERED(sl) > 0) {
++                      /* A bulk read has been issued, read the device RAM */
++                      ret = read_scratchpad(sl, &info);
++                      SLAVE_CONVERT_TRIGGERED(sl) = 0;
++              } else
++                      ret = convert_t(sl, &info);
++      } else
++              ret = convert_t(sl, &info);
+       if (ret < 0) {
+               dev_dbg(device,
+@@ -1412,6 +1616,49 @@ free_m:
+       return size;
+ }
++static ssize_t therm_bulk_read_store(struct device *device,
++      struct device_attribute *attr, const char *buf, size_t size)
++{
++      struct w1_master *dev_master = dev_to_w1_master(device);
++      int ret = -EINVAL; /* Invalid argument */
++
++      if (size == sizeof(BULK_TRIGGER_CMD))
++              if (!strncmp(buf, BULK_TRIGGER_CMD,
++                              sizeof(BULK_TRIGGER_CMD)-1))
++                      ret = trigger_bulk_read(dev_master);
++
++      if (ret)
++              dev_info(device,
++                      "%s: unable to trigger a bulk read on the bus. err=%d\n",
++                      __func__, ret);
++
++      return size;
++}
++
++static ssize_t therm_bulk_read_show(struct device *device,
++      struct device_attribute *attr, char *buf)
++{
++      struct w1_master *dev_master = dev_to_w1_master(device);
++      struct w1_slave *sl = NULL;
++      int ret = 0;
++
++      list_for_each_entry(sl, &dev_master->slist, w1_slave_entry) {
++              if (sl->family_data) {
++                      if (bulk_read_support(sl)) {
++                              if (SLAVE_CONVERT_TRIGGERED(sl) == -1) {
++                                      ret = -1;
++                                      goto show_result;
++                              }
++                              if (SLAVE_CONVERT_TRIGGERED(sl) == 1)
++                                      /* continue to check other slaves */
++                                      ret = 1;
++                      }
++              }
++      }
++show_result:
++      return sprintf(buf, "%d\n", ret);
++}
++
+ #if IS_REACHABLE(CONFIG_HWMON)
+ static int w1_read_temp(struct device *device, u32 attr, int channel,
+                       long *val)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0774-w1_therm-Free-the-correct-variable.patch b/target/linux/bcm27xx/patches-5.4/950-0774-w1_therm-Free-the-correct-variable.patch
new file mode 100644 (file)
index 0000000..fede412
--- /dev/null
@@ -0,0 +1,41 @@
+From 039babe99fda6eb04a77ca29cacf98efd1a5f406 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 20 May 2020 15:00:19 +0300
+Subject: [PATCH] w1_therm: Free the correct variable
+
+commit e420637b81f78d0fbacf539bdb1b341eba602aea upstream.
+
+The problem is that we change "p_args" to point to the middle of the
+string so when we free it at the end of the function it's not freeing
+the same pointer that we originally allocated.
+
+Fixes: e2c94d6f5720 ("w1_therm: adding alarm sysfs entry")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Link: https://lore.kernel.org/r/20200520120019.GA172354@mwanda
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_therm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -1526,8 +1526,9 @@ static ssize_t alarms_store(struct devic
+       int temp, ret = -EINVAL;
+       char *token = NULL;
+       s8 tl, th, tt;  /* 1 byte per value + temp ring order */
+-      char *p_args = kmalloc(size, GFP_KERNEL);
++      char *p_args, *orig;
++      p_args = orig = kmalloc(size, GFP_KERNEL);
+       /* Safe string copys as buf is const */
+       if (!p_args) {
+               dev_warn(device,
+@@ -1611,7 +1612,7 @@ static ssize_t alarms_store(struct devic
+ free_m:
+       /* free allocated memory */
+-      kfree(p_args);
++      kfree(orig);
+       return size;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0775-w1_therm-remove-redundant-assignments-to-variable-re.patch b/target/linux/bcm27xx/patches-5.4/950-0775-w1_therm-remove-redundant-assignments-to-variable-re.patch
new file mode 100644 (file)
index 0000000..73bc9d5
--- /dev/null
@@ -0,0 +1,58 @@
+From 7566655c9e659e890f44784a6403de98ad77ae5b Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Tue, 19 May 2020 16:45:53 +0100
+Subject: [PATCH] w1_therm: remove redundant assignments to variable
+ ret
+
+commit f37d13d52c0560bd2bac40b22466af538e61a5ce upstream.
+
+The variable ret is being initialized with a value that is never read
+and it is being updated later with a new value. The initialization
+is redundant and can be removed.
+
+Addresses-Coverity: ("Unused value")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Link: https://lore.kernel.org/r/20200519154553.873413-1-colin.king@canonical.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/w1/slaves/w1_therm.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/w1/slaves/w1_therm.c
++++ b/drivers/w1/slaves/w1_therm.c
+@@ -505,7 +505,7 @@ static inline int w1_DS18S20_write_data(
+ static inline int w1_DS18B20_set_resolution(struct w1_slave *sl, int val)
+ {
+-      int ret = -ENODEV;
++      int ret;
+       u8 new_config_register[3];      /* array of data to be written */
+       struct therm_info info;
+@@ -538,7 +538,7 @@ static inline int w1_DS18B20_set_resolut
+ static inline int w1_DS18B20_get_resolution(struct w1_slave *sl)
+ {
+-      int ret = -ENODEV;
++      int ret;
+       u8 config_register;
+       struct therm_info info;
+@@ -1499,7 +1499,7 @@ static ssize_t alarms_show(struct device
+       struct device_attribute *attr, char *buf)
+ {
+       struct w1_slave *sl = dev_to_w1_slave(device);
+-      int ret = -ENODEV;
++      int ret;
+       s8 th = 0, tl = 0;
+       struct therm_info scratchpad;
+@@ -1523,7 +1523,7 @@ static ssize_t alarms_store(struct devic
+       struct w1_slave *sl = dev_to_w1_slave(device);
+       struct therm_info info;
+       u8 new_config_register[3];      /* array of data to be written */
+-      int temp, ret = -EINVAL;
++      int temp, ret;
+       char *token = NULL;
+       s8 tl, th, tt;  /* 1 byte per value + temp ring order */
+       char *p_args, *orig;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0776-PCI-brcmstb-Assert-fundamental-reset-on-initializati.patch b/target/linux/bcm27xx/patches-5.4/950-0776-PCI-brcmstb-Assert-fundamental-reset-on-initializati.patch
new file mode 100644 (file)
index 0000000..2692bed
--- /dev/null
@@ -0,0 +1,33 @@
+From d9317f90391167ebc275696d9df3c21ce754d609 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 7 May 2020 19:20:20 +0200
+Subject: [PATCH] PCI: brcmstb: Assert fundamental reset on
+ initialization
+
+commit 22e21e51ce755399fd42055a3f668ee4af370881 upstream.
+
+While preparing the driver for upstream this detail was missed.
+
+If not asserted during the initialization process, devices connected on
+the bus will not be made aware of the internal reset happening. This,
+potentially resulting in unexpected behavior.
+
+Link: https://lore.kernel.org/r/20200507172020.18000-1-nsaenzjulienne@suse.de
+Fixes: c0452137034b ("PCI: brcmstb: Add Broadcom STB PCIe host controller driver")
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -697,6 +697,7 @@ static int brcm_pcie_setup(struct brcm_p
+       /* Reset the bridge */
+       brcm_pcie_bridge_sw_init_set(pcie, 1);
++      brcm_pcie_perst_set(pcie, 1);
+       usleep_range(100, 200);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0777-clk-rpi-Adjust-DT-binding-to-match-upstream.patch b/target/linux/bcm27xx/patches-5.4/950-0777-clk-rpi-Adjust-DT-binding-to-match-upstream.patch
new file mode 100644 (file)
index 0000000..3527870
--- /dev/null
@@ -0,0 +1,189 @@
+From d8daf6289869513ed548bcb0da410d7de3e5d57a Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Wed, 10 Jun 2020 16:28:56 +0200
+Subject: [PATCH] clk: rpi: Adjust DT binding to match upstream
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ arch/arm/boot/dts/bcm270x.dtsi             |  6 ------
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts |  5 +++++
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts      |  5 +++++
+ arch/arm/boot/dts/bcm2710-rpi-cm3.dts      |  5 +++++
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts      |  5 +++++
+ arch/arm/boot/dts/bcm2711.dtsi             |  6 ------
+ arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts |  5 +++++
+ 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.dtsi     |  5 +++++
+ drivers/clk/bcm/clk-raspberrypi.c          | 12 +++++++++++-
+ 11 files changed, 51 insertions(+), 13 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -7,12 +7,6 @@
+               /delete-property/ stdout-path;
+       };
+-      firmware_clocks: firmware-clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              raspberrypi,firmware = <&firmware>;
+-              #clock-cells = <1>;
+-      };
+-
+       soc: soc {
+               watchdog: watchdog@7e100000 {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -85,6 +85,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: expgpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -96,6 +96,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: expgpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
+@@ -58,6 +58,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: expgpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -54,6 +54,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2711.dtsi
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -24,12 +24,6 @@
+               clock-output-names = "108MHz-clock";
+       };
+-      firmware_clocks: firmware-clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              raspberrypi,firmware = <&firmware>;
+-              #clock-cells = <1>;
+-      };
+-
+       soc {
+               /*
+                * Defined ranges:
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
+@@ -31,6 +31,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+@@ -37,6 +37,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -32,6 +32,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
++++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
+@@ -35,6 +35,11 @@
+ };
+ &firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -383,13 +383,23 @@ static int raspberrypi_clk_probe(struct
+       struct raspberrypi_clk *rpi;
+       int ret;
+-      firmware_node = of_parse_phandle(dev->of_node, "raspberrypi,firmware", 0);
++      /*
++       * We can be probed either through the an old-fashioned
++       * platform device registration or through a DT node that is a
++       * child of the firmware node. Handle both cases.
++       */
++      if (dev->of_node)
++              firmware_node = of_get_parent(dev->of_node);
++      else
++              firmware_node = of_find_compatible_node(NULL, NULL,
++                                                      "raspberrypi,bcm2835-firmware");
+       if (!firmware_node) {
+               dev_err(dev, "Missing firmware node\n");
+               return -ENOENT;
+       }
+       firmware = rpi_firmware_get(firmware_node);
++      of_node_put(firmware_node);
+       if (!firmware)
+               return -EPROBE_DEFER;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0778-clk-bcm-rpi-Add-an-enum-for-the-firmware-clocks.patch b/target/linux/bcm27xx/patches-5.4/950-0778-clk-bcm-rpi-Add-an-enum-for-the-firmware-clocks.patch
new file mode 100644 (file)
index 0000000..c69b568
--- /dev/null
@@ -0,0 +1,80 @@
+From d9b492679a107e535cfd39ee00bd2ce6f12089e0 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Tue, 26 May 2020 14:23:04 +0200
+Subject: [PATCH] clk: bcm: rpi: Add an enum for the firmware clocks
+
+While the firmware allows us to discover the available clocks, we need to
+discriminate those clocks to only register the ones meaningful to Linux.
+The firmware also doesn't provide a clock name, so having a list of the ID
+will help us to give clocks a proper name later on.
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 30 ++++++++++++++++++++++++------
+ 1 file changed, 24 insertions(+), 6 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -18,7 +18,23 @@
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+-#define RPI_FIRMWARE_ARM_CLK_ID               0x00000003
++enum rpi_firmware_clk_id {
++      RPI_FIRMWARE_EMMC_CLK_ID = 1,
++      RPI_FIRMWARE_UART_CLK_ID,
++      RPI_FIRMWARE_ARM_CLK_ID,
++      RPI_FIRMWARE_CORE_CLK_ID,
++      RPI_FIRMWARE_V3D_CLK_ID,
++      RPI_FIRMWARE_H264_CLK_ID,
++      RPI_FIRMWARE_ISP_CLK_ID,
++      RPI_FIRMWARE_SDRAM_CLK_ID,
++      RPI_FIRMWARE_PIXEL_CLK_ID,
++      RPI_FIRMWARE_PWM_CLK_ID,
++      RPI_FIRMWARE_HEVC_CLK_ID,
++      RPI_FIRMWARE_EMMC2_CLK_ID,
++      RPI_FIRMWARE_M2MC_CLK_ID,
++      RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
++      RPI_FIRMWARE_NUM_CLK_ID,
++};
+ #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
+ #define RPI_FIRMWARE_STATE_WAIT_BIT   BIT(1)
+@@ -31,8 +47,6 @@
+ #define A2W_PLL_FRAC_BITS             20
+-#define NUM_FW_CLKS                   16
+-
+ struct raspberrypi_clk {
+       struct device *dev;
+       struct rpi_firmware *firmware;
+@@ -350,12 +364,15 @@ static int raspberrypi_discover_clocks(s
+       struct rpi_firmware_get_clocks_response *clks;
+       int ret;
+-      clks = devm_kcalloc(rpi->dev, sizeof(*clks), NUM_FW_CLKS, GFP_KERNEL);
++      clks = devm_kcalloc(rpi->dev,
++                          sizeof(*clks), RPI_FIRMWARE_NUM_CLK_ID,
++                          GFP_KERNEL);
+       if (!clks)
+               return -ENOMEM;
+       ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
+-                                  clks, sizeof(*clks) * NUM_FW_CLKS);
++                                  clks,
++                                  sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID);
+       if (ret)
+               return ret;
+@@ -411,7 +428,8 @@ static int raspberrypi_clk_probe(struct
+       rpi->firmware = firmware;
+       platform_set_drvdata(pdev, rpi);
+-      clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, NUM_FW_CLKS),
++      clk_data = devm_kzalloc(dev, struct_size(clk_data, hws,
++                                               RPI_FIRMWARE_NUM_CLK_ID),
+                               GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0779-clk-bcm-rpi-Use-CCF-boundaries-instead-of-rolling-ou.patch b/target/linux/bcm27xx/patches-5.4/950-0779-clk-bcm-rpi-Use-CCF-boundaries-instead-of-rolling-ou.patch
new file mode 100644 (file)
index 0000000..22f1aa6
--- /dev/null
@@ -0,0 +1,134 @@
+From cd72d75cfb216a7ef15ec8649e57b03b4fc48b62 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Wed, 27 May 2020 11:13:52 +0200
+Subject: [PATCH] clk: bcm: rpi: Use CCF boundaries instead of
+ rolling our own
+
+The raspberrypi firmware clock driver has a min_rate / max_rate clamping by
+storing the info it needs in a private structure.
+
+However, the CCF already provides such a facility, so we can switch to it
+to remove the boilerplate.
+
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 49 ++++++++++++++++++++-----------
+ 1 file changed, 32 insertions(+), 17 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -57,9 +57,6 @@ struct raspberrypi_clk_data {
+       struct clk_hw hw;
+       unsigned id;
+-      unsigned long min_rate;
+-      unsigned long max_rate;
+-
+       struct raspberrypi_clk *rpi;
+ };
+@@ -177,13 +174,11 @@ static int raspberrypi_fw_pll_set_rate(s
+ static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
+                                         struct clk_rate_request *req)
+ {
+-      struct raspberrypi_clk_data *data =
+-              container_of(hw, struct raspberrypi_clk_data, hw);
+       u64 div, final_rate;
+       u32 ndiv, fdiv;
+       /* We can't use req->rate directly as it would overflow */
+-      final_rate = clamp(req->rate, data->min_rate, data->max_rate);
++      final_rate = clamp(req->rate, req->min_rate, req->max_rate);
+       div = (u64)final_rate << A2W_PLL_FRAC_BITS;
+       do_div(div, req->best_parent_rate);
+@@ -254,16 +249,15 @@ static struct clk_hw *raspberrypi_regist
+       dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
+                min_rate, max_rate);
+-      data->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
+-      data->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
+-
+       data->hw.init = &init;
+       ret = devm_clk_hw_register(rpi->dev, &data->hw);
+-      if (ret)
+-              return ERR_PTR(ret);
++      if (!ret)
++              clk_hw_set_rate_range(&data->hw,
++                                    min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE,
++                                    max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE);
+-      return &data->hw;
++      return ret;
+ }
+ static struct clk_fixed_factor raspberrypi_clk_pllb_arm = {
+@@ -299,22 +293,22 @@ static struct clk_hw *raspberrypi_regist
+       return &raspberrypi_clk_pllb_arm.hw;
+ }
+-static long raspberrypi_fw_dumb_round_rate(struct clk_hw *hw,
+-                                         unsigned long rate,
+-                                         unsigned long *parent_rate)
++static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
++                                            struct clk_rate_request *req)
+ {
+       /*
+        * The firmware will do the rounding but that isn't part of
+        * the interface with the firmware, so we just do our best
+        * here.
+        */
+-      return rate;
++      req->rate = clamp(req->rate, req->min_rate, req->max_rate);
++      return 0;
+ }
+ static const struct clk_ops raspberrypi_firmware_clk_ops = {
+       .is_prepared    = raspberrypi_fw_is_prepared,
+       .recalc_rate    = raspberrypi_fw_get_rate,
+-      .round_rate     = raspberrypi_fw_dumb_round_rate,
++      .determine_rate = raspberrypi_fw_dumb_determine_rate,
+       .set_rate       = raspberrypi_fw_set_rate,
+ };
+@@ -324,6 +318,7 @@ static struct clk_hw *raspberrypi_clk_re
+ {
+       struct raspberrypi_clk_data *data;
+       struct clk_init_data init = {};
++      u32 min_rate, max_rate;
+       int ret;
+       if (id == RPI_FIRMWARE_ARM_CLK_ID) {
+@@ -351,10 +346,30 @@ static struct clk_hw *raspberrypi_clk_re
+       data->hw.init = &init;
++      ret = raspberrypi_clock_property(rpi->firmware, data,
++                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
++                                       &min_rate);
++      if (ret) {
++              dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
++                      init.name, ret);
++              return ERR_PTR(ret);
++      }
++
++      ret = raspberrypi_clock_property(rpi->firmware, data,
++                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
++                                       &max_rate);
++      if (ret) {
++              dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
++                      init.name, ret);
++              return ERR_PTR(ret);
++      }
++
+       ret = devm_clk_hw_register(rpi->dev, &data->hw);
+       if (ret)
+               return ERR_PTR(ret);
++      clk_hw_set_rate_range(&data->hw, min_rate, max_rate);
++
+       return &data->hw;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0780-clk-bcm-rpi-Give-firmware-clocks-a-name.patch b/target/linux/bcm27xx/patches-5.4/950-0780-clk-bcm-rpi-Give-firmware-clocks-a-name.patch
new file mode 100644 (file)
index 0000000..745e858
--- /dev/null
@@ -0,0 +1,52 @@
+From 5f69f49a942cd31e5f8b511e166fb55e3a0df267 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Tue, 26 May 2020 14:30:31 +0200
+Subject: [PATCH] clk: bcm: rpi: Give firmware clocks a name
+
+We've registered the firmware clocks using their ID as name, but it's much
+more convenient to register them using their proper name. Since the
+firmware doesn't provide it, we have to duplicate it.
+
+Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -36,6 +36,23 @@ enum rpi_firmware_clk_id {
+       RPI_FIRMWARE_NUM_CLK_ID,
+ };
++static char *rpi_firmware_clk_names[] = {
++      [RPI_FIRMWARE_EMMC_CLK_ID]      = "emmc",
++      [RPI_FIRMWARE_UART_CLK_ID]      = "uart",
++      [RPI_FIRMWARE_ARM_CLK_ID]       = "arm",
++      [RPI_FIRMWARE_CORE_CLK_ID]      = "core",
++      [RPI_FIRMWARE_V3D_CLK_ID]       = "v3d",
++      [RPI_FIRMWARE_H264_CLK_ID]      = "h264",
++      [RPI_FIRMWARE_ISP_CLK_ID]       = "isp",
++      [RPI_FIRMWARE_SDRAM_CLK_ID]     = "sdram",
++      [RPI_FIRMWARE_PIXEL_CLK_ID]     = "pixel",
++      [RPI_FIRMWARE_PWM_CLK_ID]       = "pwm",
++      [RPI_FIRMWARE_HEVC_CLK_ID]      = "hevc",
++      [RPI_FIRMWARE_EMMC2_CLK_ID]     = "emmc2",
++      [RPI_FIRMWARE_M2MC_CLK_ID]      = "m2mc",
++      [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb",
++};
++
+ #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
+ #define RPI_FIRMWARE_STATE_WAIT_BIT   BIT(1)
+@@ -340,7 +357,9 @@ static struct clk_hw *raspberrypi_clk_re
+       data->rpi = rpi;
+       data->id = id;
+-      init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, "fw-clk-%u", id);
++      init.name = devm_kasprintf(rpi->dev, GFP_KERNEL,
++                                 "fw-clk-%s",
++                                 rpi_firmware_clk_names[id]);
+       init.ops = &raspberrypi_firmware_clk_ops;
+       init.flags = CLK_GET_RATE_NOCACHE;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0781-clk-bcm-rpi-Remove-the-quirks-for-the-CPU-clock.patch b/target/linux/bcm27xx/patches-5.4/950-0781-clk-bcm-rpi-Remove-the-quirks-for-the-CPU-clock.patch
new file mode 100644 (file)
index 0000000..0e9bb9c
--- /dev/null
@@ -0,0 +1,207 @@
+From 30ae66617ee6f340343c8e75c244e370721ed2eb Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Tue, 26 May 2020 15:27:35 +0200
+Subject: [PATCH] clk: bcm: rpi: Remove the quirks for the CPU clock
+
+The CPU clock has had so far a bunch of quirks to expose the clock tree
+properly, but since we reverted to exposing them through the MMIO driver,
+we can remove that code from the firmware driver.
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 163 ++----------------------------
+ 1 file changed, 9 insertions(+), 154 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -151,13 +151,6 @@ static unsigned long raspberrypi_fw_get_
+       return val;
+ }
+-static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
+-                                               unsigned long parent_rate)
+-{
+-      return raspberrypi_fw_get_rate(hw, parent_rate) *
+-              RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
+-}
+-
+ static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+ {
+@@ -176,140 +169,6 @@ static int raspberrypi_fw_set_rate(struc
+       return ret;
+ }
+-static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+-                                     unsigned long parent_rate)
+-{
+-      u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
+-
+-      return raspberrypi_fw_set_rate(hw, new_rate, parent_rate);
+-}
+-
+-/*
+- * Sadly there is no firmware rate rounding interface. We borrowed it from
+- * clk-bcm2835.
+- */
+-static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
+-                                        struct clk_rate_request *req)
+-{
+-      u64 div, final_rate;
+-      u32 ndiv, fdiv;
+-
+-      /* We can't use req->rate directly as it would overflow */
+-      final_rate = clamp(req->rate, req->min_rate, req->max_rate);
+-
+-      div = (u64)final_rate << A2W_PLL_FRAC_BITS;
+-      do_div(div, req->best_parent_rate);
+-
+-      ndiv = div >> A2W_PLL_FRAC_BITS;
+-      fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
+-
+-      final_rate = ((u64)req->best_parent_rate *
+-                                      ((ndiv << A2W_PLL_FRAC_BITS) + fdiv));
+-
+-      req->rate = final_rate >> A2W_PLL_FRAC_BITS;
+-
+-      return 0;
+-}
+-
+-static const struct clk_ops raspberrypi_firmware_pll_clk_ops = {
+-      .is_prepared = raspberrypi_fw_is_prepared,
+-      .recalc_rate = raspberrypi_fw_pll_get_rate,
+-      .set_rate = raspberrypi_fw_pll_set_rate,
+-      .determine_rate = raspberrypi_pll_determine_rate,
+-};
+-
+-static struct clk_hw *raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
+-{
+-      struct raspberrypi_clk_data *data;
+-      struct clk_init_data init = {};
+-      u32 min_rate = 0, max_rate = 0;
+-      int ret;
+-
+-      data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
+-      if (!data)
+-              return ERR_PTR(-ENOMEM);
+-      data->rpi = rpi;
+-      data->id = RPI_FIRMWARE_ARM_CLK_ID;
+-
+-      /* All of the PLLs derive from the external oscillator. */
+-      init.parent_names = (const char *[]){ "osc" };
+-      init.num_parents = 1;
+-      init.name = "pllb";
+-      init.ops = &raspberrypi_firmware_pll_clk_ops;
+-      init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;
+-
+-      /* Get min & max rates set by the firmware */
+-      ret = raspberrypi_clock_property(rpi->firmware, data,
+-                                       RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
+-                                       &min_rate);
+-      if (ret) {
+-              dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
+-                      init.name, ret);
+-              return ERR_PTR(ret);
+-      }
+-
+-      ret = raspberrypi_clock_property(rpi->firmware, data,
+-                                       RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+-                                       &max_rate);
+-      if (ret) {
+-              dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
+-                      init.name, ret);
+-              return ERR_PTR(ret);
+-      }
+-
+-      if (!min_rate || !max_rate) {
+-              dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
+-                      min_rate, max_rate);
+-              return ERR_PTR(-EINVAL);
+-      }
+-
+-      dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
+-               min_rate, max_rate);
+-
+-      data->hw.init = &init;
+-
+-      ret = devm_clk_hw_register(rpi->dev, &data->hw);
+-      if (!ret)
+-              clk_hw_set_rate_range(&data->hw,
+-                                    min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE,
+-                                    max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE);
+-
+-      return ret;
+-}
+-
+-static struct clk_fixed_factor raspberrypi_clk_pllb_arm = {
+-      .mult = 1,
+-      .div = 2,
+-      .hw.init = &(struct clk_init_data) {
+-              .name           = "pllb_arm",
+-              .parent_names   = (const char *[]){ "pllb" },
+-              .num_parents    = 1,
+-              .ops            = &clk_fixed_factor_ops,
+-              .flags          = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+-      },
+-};
+-
+-static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
+-{
+-      int ret;
+-
+-      ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw);
+-      if (ret) {
+-              dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
+-              return ERR_PTR(ret);
+-      }
+-
+-      ret = devm_clk_hw_register_clkdev(rpi->dev,
+-                                        &raspberrypi_clk_pllb_arm.hw,
+-                                        NULL, "cpu0");
+-      if (ret) {
+-              dev_err(rpi->dev, "Failed to initialize clkdev\n");
+-              return ERR_PTR(ret);
+-      }
+-
+-      return &raspberrypi_clk_pllb_arm.hw;
+-}
+-
+ static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
+                                             struct clk_rate_request *req)
+ {
+@@ -338,19 +197,6 @@ static struct clk_hw *raspberrypi_clk_re
+       u32 min_rate, max_rate;
+       int ret;
+-      if (id == RPI_FIRMWARE_ARM_CLK_ID) {
+-              struct clk_hw *hw;
+-
+-              hw = raspberrypi_register_pllb(rpi);
+-              if (IS_ERR(hw)) {
+-                      dev_err(rpi->dev, "Failed to initialize pllb, %ld\n",
+-                              PTR_ERR(hw));
+-                      return hw;
+-              }
+-
+-              return raspberrypi_register_pllb_arm(rpi);
+-      }
+-
+       data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return ERR_PTR(-ENOMEM);
+@@ -389,6 +235,15 @@ static struct clk_hw *raspberrypi_clk_re
+       clk_hw_set_rate_range(&data->hw, min_rate, max_rate);
++      if (id == RPI_FIRMWARE_ARM_CLK_ID) {
++              ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw,
++                                                NULL, "cpu0");
++              if (ret) {
++                      dev_err(rpi->dev, "Failed to initialize clkdev\n");
++                      return ERR_PTR(ret);
++              }
++      }
++
+       return &data->hw;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0782-clk-rpi-Only-register-a-few-firmware-clocks.patch b/target/linux/bcm27xx/patches-5.4/950-0782-clk-rpi-Only-register-a-few-firmware-clocks.patch
new file mode 100644 (file)
index 0000000..580a90c
--- /dev/null
@@ -0,0 +1,43 @@
+From 73a8443ea82fef7a1f8a466fff83da7863baed49 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Wed, 10 Jun 2020 16:18:17 +0200
+Subject: [PATCH] clk: rpi: Only register a few firmware clocks
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -268,13 +268,24 @@ static int raspberrypi_discover_clocks(s
+       while (clks->id) {
+               struct clk_hw *hw;
+-              hw = raspberrypi_clk_register(rpi, clks->parent, clks->id);
+-              if (IS_ERR(hw))
+-                      return PTR_ERR(hw);
++              switch (clks->id) {
++              case RPI_FIRMWARE_ARM_CLK_ID:
++              case RPI_FIRMWARE_CORE_CLK_ID:
++              case RPI_FIRMWARE_M2MC_CLK_ID:
++              case RPI_FIRMWARE_V3D_CLK_ID:
++                      hw = raspberrypi_clk_register(rpi, clks->parent,
++                                                    clks->id);
++                      if (IS_ERR(hw))
++                              return PTR_ERR(hw);
+-              data->hws[clks->id] = hw;
+-              data->num = clks->id + 1;
+-              clks++;
++                      data->hws[clks->id] = hw;
++                      data->num = clks->id + 1;
++                      fallthrough;
++
++              default:
++                      clks++;
++                      break;
++              }
+       }
+       return 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0783-clk-rpi-Fix-compatible-indentation.patch b/target/linux/bcm27xx/patches-5.4/950-0783-clk-rpi-Fix-compatible-indentation.patch
new file mode 100644 (file)
index 0000000..da9d3b8
--- /dev/null
@@ -0,0 +1,23 @@
+From 4a1d8af9737868f6494f491e9a1efb0fb348588e Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Wed, 10 Jun 2020 16:29:08 +0200
+Subject: [PATCH] clk: rpi: Fix compatible indentation
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/bcm/clk-raspberrypi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/bcm/clk-raspberrypi.c
++++ b/drivers/clk/bcm/clk-raspberrypi.c
+@@ -359,8 +359,8 @@ static int raspberrypi_clk_remove(struct
+ }
+ static const struct of_device_id raspberrypi_clk_match[] = {
+-        { .compatible = "raspberrypi,firmware-clocks" },
+-        { },
++      { .compatible = "raspberrypi,firmware-clocks" },
++      { },
+ };
+ MODULE_DEVICE_TABLE(of, raspberrypi_clk_match);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0784-SQUASH-dts-Fix-firmware-clocks-support.patch b/target/linux/bcm27xx/patches-5.4/950-0784-SQUASH-dts-Fix-firmware-clocks-support.patch
new file mode 100644 (file)
index 0000000..35c2c44
--- /dev/null
@@ -0,0 +1,176 @@
+From 10f7562d7ce7ea6fe6324df059c865ff660811fc Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 11 Jun 2020 16:34:00 +0100
+Subject: [PATCH] SQUASH: dts: Fix firmware clocks support
+
+Commit [1] touched a lot of files and still missed some platforms.
+In particular, Pi 2 was left with no clock scaling. Simplify the
+firmware clocks DTS support and extend it to all platforms that
+use the raspberrypi-cpufreq driver.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2709-rpi.dtsi         | 7 +++++++
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 5 -----
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts      | 5 -----
+ arch/arm/boot/dts/bcm2710-rpi-cm3.dts      | 5 -----
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts      | 5 -----
+ arch/arm/boot/dts/bcm2711-rpi.dtsi         | 7 +++++++
+ arch/arm/boot/dts/bcm2836-rpi.dtsi         | 7 +++++++
+ arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts | 5 -----
+ 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.dtsi     | 5 -----
+ 11 files changed, 21 insertions(+), 40 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2709-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2709-rpi.dtsi
+@@ -3,3 +3,10 @@
+ &vchiq {
+       compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
+ };
++
++&firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++};
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -85,11 +85,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: expgpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -96,11 +96,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: expgpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
+@@ -58,11 +58,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: expgpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -54,11 +54,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -170,3 +170,10 @@
+ &genet {
+       compatible = "brcm,bcm2711-genet-v5", "brcm,genet-v5";
+ };
++
++&firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++};
+--- a/arch/arm/boot/dts/bcm2836-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
+@@ -4,3 +4,10 @@
+ &vchiq {
+       compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
+ };
++
++&firmware {
++      firmware_clocks: clocks {
++              compatible = "raspberrypi,firmware-clocks";
++              #clock-cells = <1>;
++      };
++};
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
+@@ -31,11 +31,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+@@ -37,11 +37,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+@@ -32,11 +32,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
+--- a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
++++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
+@@ -35,11 +35,6 @@
+ };
+ &firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-
+       expgpio: gpio {
+               compatible = "raspberrypi,firmware-gpio";
+               gpio-controller;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch b/target/linux/bcm27xx/patches-5.4/950-0785-ARM-dts-Add-bcm2711-rpi-cm4.dts.patch
new file mode 100644 (file)
index 0000000..fa6837b
--- /dev/null
@@ -0,0 +1,631 @@
+From 104dcc1aff0ae5509ad9875c11e3e0d8c290709d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 2 Jun 2020 17:19:51 +0100
+Subject: [PATCH] ARM: dts: Add bcm2711-rpi-cm4.dts
+
+Add initial DTS file for Compute Module 4.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/Makefile            |   3 +-
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 586 ++++++++++++++++++++++++++
+ arch/arm/boot/dts/overlays/README     |   6 +
+ 3 files changed, 594 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -12,7 +12,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2710-rpi-3-b.dtb \
+       bcm2711-rpi-4-b.dtb \
+       bcm2710-rpi-3-b-plus.dtb \
+-      bcm2710-rpi-cm3.dtb
++      bcm2710-rpi-cm3.dtb \
++      bcm2711-rpi-cm4.dtb
+ dtb-$(CONFIG_ARCH_ALPINE) += \
+       alpine-db.dtb
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -0,0 +1,586 @@
++// SPDX-License-Identifier: GPL-2.0
++/dts-v1/;
++#include "bcm2711.dtsi"
++#include "bcm2835-rpi.dtsi"
++
++/ {
++      compatible = "raspberrypi,4-compute-module", "brcm,bcm2711";
++      model = "Raspberry Pi Compute Module 4";
++
++      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 {
++              ethernet0 = &genet;
++      };
++
++      leds {
++              act {
++                      gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
++              };
++
++              pwr {
++                      label = "PWR";
++                      gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++              };
++      };
++
++      wifi_pwrseq: wifi-pwrseq {
++              compatible = "mmc-pwrseq-simple";
++              reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
++      };
++
++      sd_io_1v8_reg: sd_io_1v8_reg {
++              compatible = "regulator-gpio";
++              regulator-name = "vdd-sd-io";
++              regulator-min-microvolt = <1800000>;
++              regulator-max-microvolt = <3300000>;
++              regulator-boot-on;
++              regulator-always-on;
++              regulator-settling-time-us = <5000>;
++              gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
++              states = <1800000 0x1
++                        3300000 0x0>;
++              status = "okay";
++      };
++};
++
++&firmware {
++      expgpio: gpio {
++              compatible = "raspberrypi,firmware-gpio";
++              gpio-controller;
++              #gpio-cells = <2>;
++              gpio-line-names = "BT_ON",
++                                "WL_ON",
++                                "PWR_LED_OFF",
++                                "ANT1",
++                                "VDD_SD_IO_SEL",
++                                "CAM_GPIO",
++                                "SD_PWR_ON",
++                                "ANT2";
++              status = "okay";
++
++              ant1: ant1 {
++                      gpio-hog;
++                      gpios = <3 GPIO_ACTIVE_HIGH>;
++                      output-high;
++              };
++
++              ant2: ant2 {
++                      gpio-hog;
++                      gpios = <7 GPIO_ACTIVE_HIGH>;
++                      output-low;
++              };
++      };
++};
++
++&pwm1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
++      status = "okay";
++};
++
++/* SDHCI is used to control the SDIO for wireless */
++&sdhci {
++      #address-cells = <1>;
++      #size-cells = <0>;
++      pinctrl-names = "default";
++      pinctrl-0 = <&emmc_gpio34>;
++      bus-width = <4>;
++      non-removable;
++      mmc-pwrseq = <&wifi_pwrseq>;
++      status = "okay";
++
++      brcmf: wifi@1 {
++              reg = <1>;
++              compatible = "brcm,bcm4329-fmac";
++      };
++};
++
++/* EMMC2 is used to drive the SD card */
++&emmc2 {
++      vqmmc-supply = <&sd_io_1v8_reg>;
++      broken-cd;
++      status = "okay";
++};
++
++&genet {
++      phy-handle = <&phy1>;
++      phy-mode = "rgmii-rxid";
++      status = "okay";
++};
++
++&genet_mdio {
++      phy1: ethernet-phy@1 {
++              /* No PHY interrupt */
++              reg = <0x1>;
++      };
++};
++
++/* uart0 communicates with the BT module */
++&uart0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32>;
++      uart-has-rtscts;
++      status = "okay";
++
++      bluetooth {
++              compatible = "brcm,bcm43438-bt";
++              max-speed = <2000000>;
++              shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
++      };
++};
++
++/* uart1 is mapped to the pin header */
++&uart1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart1_gpio14>;
++      status = "okay";
++};
++
++&vchiq {
++      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++&vc4 {
++      status = "okay";
++};
++
++&pixelvalve0 {
++      status = "okay";
++};
++
++&pixelvalve1 {
++      status = "okay";
++};
++
++&pixelvalve2 {
++      status = "okay";
++};
++
++&pixelvalve3 {
++      status = "okay";
++};
++
++&pixelvalve4 {
++      status = "okay";
++};
++
++&hdmi0 {
++      status = "okay";
++};
++
++&ddc0 {
++      status = "okay";
++};
++
++&hdmi1 {
++      status = "okay";
++};
++
++&ddc1 {
++      status = "okay";
++};
++
++// =============================================
++// Downstream rpi- changes
++
++#include "bcm270x.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"
++
++/delete-node/ &emmc2;
++
++/ {
++      chosen {
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++      };
++
++      aliases {
++              serial0 = &uart1;
++              serial1 = &uart0;
++              mmc0 = &emmc2;
++              mmc1 = &mmcnr;
++              mmc2 = &sdhost;
++              /delete-property/ i2c2;
++              i2c3 = &i2c3;
++              i2c4 = &i2c4;
++              i2c5 = &i2c5;
++              i2c6 = &i2c6;
++              /delete-property/ ethernet;
++              /delete-property/ intc;
++              pcie0 = &pcie0;
++              emmc2bus = &emmc2bus;
++      };
++
++      emmc2bus: emmc2bus {
++              compatible = "simple-bus";
++              #address-cells = <2>;
++              #size-cells = <1>;
++
++              ranges = <0x0 0x7e000000  0x0 0xfe000000  0x01800000>;
++              dma-ranges = <0x0 0xc0000000  0x0 0x00000000  0x40000000>;
++
++              emmc2: emmc2@7e340000 {
++                      compatible = "brcm,bcm2711-emmc2";
++                      status = "okay";
++                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
++                      reg = <0x0 0x7e340000 0x100>;
++                      vqmmc-supply = <&sd_io_1v8_reg>;
++                      broken-cd;
++              };
++      };
++
++      /delete-node/ wifi-pwrseq;
++};
++
++&mmcnr {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdio_pins>;
++      bus-width = <4>;
++      status = "okay";
++};
++
++&uart0 {
++      pinctrl-0 = <&uart0_pins &bt_pins>;
++      status = "okay";
++
++      /delete-node/ bluetooth;
++};
++
++&uart1 {
++      pinctrl-0 = <&uart1_pins>;
++};
++
++&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 = <BCM2835_FSEL_ALT0>;
++      };
++
++      spi0_cs_pins: spi0_cs_pins {
++              brcm,pins = <8 7>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi3_pins: spi3_pins {
++              brcm,pins = <1 2 3>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi3_cs_pins: spi3_cs_pins {
++              brcm,pins = <0 24>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi4_pins: spi4_pins {
++              brcm,pins = <5 6 7>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi4_cs_pins: spi4_cs_pins {
++              brcm,pins = <4 25>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi5_pins: spi5_pins {
++              brcm,pins = <13 14 15>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi5_cs_pins: spi5_cs_pins {
++              brcm,pins = <12 26>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi6_pins: spi6_pins {
++              brcm,pins = <19 20 21>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi6_cs_pins: spi6_cs_pins {
++              brcm,pins = <18 27>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      i2c0_pins: i2c0 {
++              brcm,pins = <0 1>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c1_pins: i2c1 {
++              brcm,pins = <2 3>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c3_pins: i2c3 {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c4_pins: i2c4 {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c5_pins: i2c5 {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c6_pins: i2c6 {
++              brcm,pins = <22 23>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2s_pins: i2s {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++      };
++
++      sdio_pins: sdio_pins {
++              brcm,pins =     <34 35 36 37 38 39>;
++              brcm,function = <BCM2835_FSEL_ALT3>; // alt3 = SD1
++              brcm,pull =     <0 2 2 2 2 2>;
++      };
++
++      bt_pins: bt_pins {
++              brcm,pins = "-"; // non-empty to keep btuart happy, //4 = 0
++                               // to fool pinctrl
++              brcm,function = <0>;
++              brcm,pull = <2>;
++      };
++
++      uart0_pins: uart0_pins {
++              brcm,pins = <32 33>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++              brcm,pull = <0 2>;
++      };
++
++      uart1_pins: uart1_pins {
++              brcm,pins;
++              brcm,function;
++              brcm,pull;
++      };
++
++      uart2_pins: uart2_pins {
++              brcm,pins = <0 1>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <0 2>;
++      };
++
++      uart3_pins: uart3_pins {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <0 2>;
++      };
++
++      uart4_pins: uart4_pins {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <0 2>;
++      };
++
++      uart5_pins: uart5_pins {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              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>;
++};
++
++/ {
++      __overrides__ {
++              /delete-property/ i2c2_baudrate;
++              /delete-property/ i2c2_iknowwhatimdoing;
++      };
++};
++
++// =============================================
++// Board specific stuff here
++
++/ {
++      sd_vcc_reg: sd_vcc_reg {
++              compatible = "regulator-fixed";
++              regulator-name = "vcc-sd";
++              regulator-min-microvolt = <3300000>;
++              regulator-max-microvolt = <3300000>;
++              regulator-boot-on;
++              enable-active-high;
++              gpio = <&expgpio 6 GPIO_ACTIVE_HIGH>;
++      };
++};
++
++&sdhost {
++      status = "disabled";
++};
++
++&emmc2 {
++      vmmc-supply = <&sd_vcc_reg>;
++      bus-width = <8>;
++};
++
++&phy1 {
++      led-modes = <0x00 0x08>; /* link/activity link */
++};
++
++&gpio {
++      audio_pins: audio_pins {
++              brcm,pins = <40 41>;
++              brcm,function = <4>;
++      };
++};
++
++&leds {
++      act_led: act {
++              label = "led0";
++              linux,default-trigger = "mmc0";
++              gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
++      };
++
++      pwr_led: pwr {
++              label = "led1";
++              linux,default-trigger = "default-on";
++              gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++      };
++};
++
++&pwm1 {
++      status = "disabled";
++};
++
++&audio {
++      pinctrl-names = "default";
++      pinctrl-0 = <&audio_pins>;
++};
++
++&vc4 {
++      status = "disabled";
++};
++
++&pixelvalve0 {
++      status = "disabled";
++};
++
++&pixelvalve1 {
++      status = "disabled";
++};
++
++&pixelvalve2 {
++      status = "disabled";
++};
++
++&pixelvalve3 {
++      status = "disabled";
++};
++
++&pixelvalve4 {
++      status = "disabled";
++};
++
++&hdmi0 {
++      status = "disabled";
++};
++
++&ddc0 {
++      status = "disabled";
++};
++
++&hdmi1 {
++      status = "disabled";
++};
++
++&ddc1 {
++      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";
++
++              pwr_led_gpio = <&pwr_led>,"gpios:4";
++              pwr_led_activelow = <&pwr_led>,"gpios:8";
++              pwr_led_trigger = <&pwr_led>,"linux,default-trigger";
++
++              eth_led0 = <&phy1>,"led-modes:0";
++              eth_led1 = <&phy1>,"led-modes:4";
++
++              ant1 =  <&ant1>,"output-high?=on",
++                      <&ant1>, "output-low?=off",
++                      <&ant2>, "output-high?=off",
++                      <&ant2>, "output-low?=on";
++              ant2 =  <&ant1>,"output-high?=off",
++                      <&ant1>, "output-low?=on",
++                      <&ant2>, "output-high?=on",
++                      <&ant2>, "output-low?=off";
++              noant = <&ant1>,"output-high?=off",
++                      <&ant1>, "output-low?=on",
++                      <&ant2>, "output-high?=off",
++                      <&ant2>, "output-low?=on";
++
++              spi_dma4 = <&spi0>, "dmas:0=", <&dma40>,
++                         <&spi0>, "dmas:8=", <&dma40>;
++      };
++};
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -92,6 +92,12 @@ Name:   <The base DTB>
+ Info:   Configures the base Raspberry Pi hardware
+ Load:   <loaded automatically>
+ Params:
++        ant1                    Select antenna 1 (default). CM4 only.
++
++        ant2                    Select antenna 2. CM4 only.
++
++        noant                   Disable both antennas. CM4 only.
++
+         audio                   Set to "on" to enable the onboard ALSA audio
+                                 interface (default "off")
diff --git a/target/linux/bcm27xx/patches-5.4/950-0786-PCI-brcmstb-Add-DT-property-to-control-L1SS.patch b/target/linux/bcm27xx/patches-5.4/950-0786-PCI-brcmstb-Add-DT-property-to-control-L1SS.patch
new file mode 100644 (file)
index 0000000..1d54cff
--- /dev/null
@@ -0,0 +1,79 @@
+From faca7230ba711f7f966cd51bf46f83c5848a8623 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 11 Jun 2020 09:57:03 +0100
+Subject: [PATCH] PCI: brcmstb: Add DT property to control L1SS
+
+The BRCM PCIe block has controls to enable control of the CLKREQ#
+signal by the L1SS, and to gate the refclk with the CLKREQ# input.
+These controls are mutually exclusive - the upstream code sets the
+latter, but some use cases require the former.
+
+Add a Device Tree property - brcm,enable-l1ss - to switch to the
+L1SS configuration.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/pci/controller/pcie-brcmstb.c | 30 ++++++++++++++++++++-------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -102,8 +102,9 @@
+               PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
+ #define PCIE_MISC_HARD_PCIE_HARD_DEBUG                                        0x4204
+-#define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK      0x2
+-#define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK              0x08000000
++#define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK      BIT(1)
++#define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK               BIT(21)
++#define  PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK              BIT(27)
+ #define PCIE_MSI_INTR2_STATUS                         0x4500
+ #define PCIE_MSI_INTR2_CLR                            0x4508
+@@ -170,6 +171,7 @@ struct brcm_pcie {
+       struct pci_bus          *root_bus;
+       struct device_node      *np;
+       bool                    ssc;
++      bool                    l1ss;
+       int                     gen;
+       u64                     msi_target_addr;
+       struct brcm_msi         *msi;
+@@ -834,12 +836,25 @@ static int brcm_pcie_setup(struct brcm_p
+               PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
+       writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
+-      /*
+-       * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
+-       * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
+-       */
+       tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
+-      tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
++      if (pcie->l1ss) {
++              /*
++               * Enable CLKREQ# signalling include L1 Substate control of
++               * the CLKREQ# signal and the external reference clock buffer.
++               * meet requirement for Endpoints that require CLKREQ#
++               * assertion to clock active within 400ns.
++               */
++              tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
++              tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK;
++      } else {
++              /*
++               * Refclk from RC should be gated with CLKREQ# input when
++               * ASPM L0s,L1 is enabled => setting the CLKREQ_DEBUG_ENABLE
++               * field to 1.
++               */
++              tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK;
++              tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
++      }
+       writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
+       return 0;
+@@ -944,6 +959,7 @@ static int brcm_pcie_probe(struct platfo
+       pcie->gen = (ret < 0) ? 0 : ret;
+       pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc");
++      pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss");
+       ret = pci_parse_request_of_pci_ranges(pcie->dev, &bridge->windows,
+                                             &bridge->dma_ranges, NULL);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0787-ARM-dts-Set-brcm-enable-l1ss-for-CM4.patch b/target/linux/bcm27xx/patches-5.4/950-0787-ARM-dts-Set-brcm-enable-l1ss-for-CM4.patch
new file mode 100644 (file)
index 0000000..4b53564
--- /dev/null
@@ -0,0 +1,27 @@
+From a883d8b6624ea9b924323920cac080cb68e02110 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 11 Jun 2020 11:22:38 +0100
+Subject: [PATCH] ARM: dts: Set brcm,enable-l1ss for CM4
+
+Enable the PCIE L1SS on Compute Module 4. It's possible that this is
+also the right thing to do for Pi 4, but it has been working as is
+up to now.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -252,6 +252,10 @@
+       /delete-node/ wifi-pwrseq;
+ };
++&pcie0 {
++       brcm,enable-l1ss;
++};
++
+ &mmcnr {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio_pins>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0788-Revert-SQUASH-Fix-spi-driver-compiler-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-0788-Revert-SQUASH-Fix-spi-driver-compiler-warnings.patch
new file mode 100644 (file)
index 0000000..437e5ab
--- /dev/null
@@ -0,0 +1,23 @@
+From 34072d0778e21edf69455d900b8a16be6b9ac95c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 16 Jun 2020 10:23:03 +0100
+Subject: [PATCH] Revert "SQUASH: Fix spi driver compiler warnings"
+
+This reverts commit fe3f696b7e5229678ae45d1293e97b5ecc00c245.
+
+See: https://github.com/raspberrypi/linux/pull/3687
+---
+ drivers/spi/spi-bcm2835.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -1182,6 +1182,8 @@ static int bcm2835_spi_setup(struct spi_
+ {
+       struct spi_controller *ctlr = spi->controller;
+       struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
++      struct gpio_chip *chip;
++      enum gpio_lookup_flags lflags;
+       u32 cs;
+       /*
diff --git a/target/linux/bcm27xx/patches-5.4/950-0789-Revert-spi-spi-bcm2835-Disable-forced-software-CS.patch b/target/linux/bcm27xx/patches-5.4/950-0789-Revert-spi-spi-bcm2835-Disable-forced-software-CS.patch
new file mode 100644 (file)
index 0000000..1479335
--- /dev/null
@@ -0,0 +1,59 @@
+From 1d78f72cb5a387922870e2a54228be25f84f95f6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 16 Jun 2020 10:23:29 +0100
+Subject: [PATCH] Revert "spi: spi-bcm2835: Disable forced software
+ CS"
+
+This reverts commit 2697f0186db346176832b8eb79adaf5c874681e8.
+
+See: https://github.com/raspberrypi/linux/pull/3687
+---
+ drivers/spi/spi-bcm2835.c | 37 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+--- a/drivers/spi/spi-bcm2835.c
++++ b/drivers/spi/spi-bcm2835.c
+@@ -1235,6 +1235,43 @@ static int bcm2835_spi_setup(struct spi_
+               return -EINVAL;
+       }
++      /*
++       * Translate native CS to GPIO
++       *
++       * FIXME: poking around in the gpiolib internals like this is
++       * not very good practice. Find a way to locate the real problem
++       * and fix it. Why is the GPIO descriptor in spi->cs_gpiod
++       * sometimes not assigned correctly? Erroneous device trees?
++       */
++
++      /* get the gpio chip for the base */
++      chip = gpiochip_find("pinctrl-bcm2835", chip_match_name);
++      if (!chip)
++              return 0;
++
++      /*
++       * Retrieve the corresponding GPIO line used for CS.
++       * The inversion semantics will be handled by the GPIO core
++       * code, so we pass GPIOS_OUT_LOW for "unasserted" and
++       * the correct flag for inversion semantics. The SPI_CS_HIGH
++       * on spi->mode cannot be checked for polarity in this case
++       * as the flag use_gpio_descriptors enforces SPI_CS_HIGH.
++       */
++      if (of_property_read_bool(spi->dev.of_node, "spi-cs-high"))
++              lflags = GPIO_ACTIVE_HIGH;
++      else
++              lflags = GPIO_ACTIVE_LOW;
++      spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select,
++                                                DRV_NAME,
++                                                lflags,
++                                                GPIOD_OUT_LOW);
++      if (IS_ERR(spi->cs_gpiod))
++              return PTR_ERR(spi->cs_gpiod);
++
++      /* and set up the "mode" and level */
++      dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n",
++               spi->chip_select);
++
+       return 0;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0790-media-irs1125-Using-i2c_transfer-for-ic2-reads.patch b/target/linux/bcm27xx/patches-5.4/950-0790-media-irs1125-Using-i2c_transfer-for-ic2-reads.patch
new file mode 100644 (file)
index 0000000..c68c6ea
--- /dev/null
@@ -0,0 +1,65 @@
+From 167060f4e3303200d373ca55a39ba4b4c55adbcc Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Tue, 16 Jun 2020 13:24:31 +0200
+Subject: [PATCH] media: irs1125: Using i2c_transfer for ic2 reads
+
+Reading data over i2c is done by using i2c_transfer to ensure that this
+operation can't be interrupted.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ drivers/media/i2c/irs1125.c | 37 ++++++++++++++++++++++---------------
+ 1 file changed, 22 insertions(+), 15 deletions(-)
+
+--- a/drivers/media/i2c/irs1125.c
++++ b/drivers/media/i2c/irs1125.c
+@@ -248,27 +248,34 @@ static int irs1125_write(struct v4l2_sub
+ static int irs1125_read(struct v4l2_subdev *sd, u16 reg, u16 *val)
+ {
+-      int ret;
+-      unsigned char data_w[2] = { reg >> 8, reg & 0xff };
+-      char rdval[2];
+-
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
++      struct i2c_msg msgs[2];
++      u8 addr_buf[2] = { reg >> 8, reg & 0xff };
++      u8 data_buf[2] = { 0, };
++      int ret;
+-      ret = i2c_master_send(client, data_w, 2);
+-      if (ret < 0) {
+-              dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
+-                      __func__, reg);
++      /* Write register address */
++      msgs[0].addr = client->addr;
++      msgs[0].flags = 0;
++      msgs[0].len = ARRAY_SIZE(addr_buf);
++      msgs[0].buf = addr_buf;
++
++      /* Read data from register */
++      msgs[1].addr = client->addr;
++      msgs[1].flags = I2C_M_RD;
++      msgs[1].len = 2;
++      msgs[1].buf = data_buf;
++
++      ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
++      if (ret != ARRAY_SIZE(msgs)) {
++              if (ret >= 0)
++                      ret = -EIO;
+               return ret;
+       }
+-      ret = i2c_master_recv(client, rdval, 2);
+-      if (ret < 0)
+-              dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
+-                      __func__, reg);
+-
+-      *val = rdval[1] | (rdval[0] << 8);
++      *val = data_buf[1] | (data_buf[0] << 8);
+-      return ret;
++      return 0;
+ }
+ static int irs1125_write_array(struct v4l2_subdev *sd,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0791-media-irs1125-Refactoring-and-debug-messages.patch b/target/linux/bcm27xx/patches-5.4/950-0791-media-irs1125-Refactoring-and-debug-messages.patch
new file mode 100644 (file)
index 0000000..c26ab8f
--- /dev/null
@@ -0,0 +1,123 @@
+From 6ba58915e8c2f884d17b651d68535959f9eff97d Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Tue, 16 Jun 2020 13:27:42 +0200
+Subject: [PATCH] media: irs1125: Refactoring and debug messages
+
+Changed some variable names to comply with checkpatch --strict mode.
+Debug messages added.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ drivers/media/i2c/irs1125.c | 36 ++++++++++++++++++++----------------
+ 1 file changed, 20 insertions(+), 16 deletions(-)
+
+--- a/drivers/media/i2c/irs1125.c
++++ b/drivers/media/i2c/irs1125.c
+@@ -15,6 +15,7 @@
+ #include "irs1125.h"
+ #include <linux/clk.h>
+ #include <linux/delay.h>
++#include <linux/firmware.h>
+ #include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
+@@ -22,13 +23,13 @@
+ #include <linux/module.h>
+ #include <linux/of_graph.h>
+ #include <linux/slab.h>
++#include <linux/types.h>
+ #include <linux/videodev2.h>
+-#include <linux/firmware.h>
++#include <media/v4l2-ctrls.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-fwnode.h>
+ #include <media/v4l2-image-sizes.h>
+ #include <media/v4l2-mediabus.h>
+-#include <media/v4l2-ctrls.h>
+ #define CHECK_BIT(val, pos) ((val) & BIT(pos))
+@@ -38,18 +39,19 @@
+ #define IRS1125_ALTERNATE_FW "irs1125_af.bin"
+-#define IRS1125_REG_CSICFG       0xA882
+-#define IRS1125_REG_DESIGN_STEP        0xB0AD
+-#define IRS1125_REG_EFUSEVAL2  0xB09F
+-#define IRS1125_REG_EFUSEVAL3  0xB0A0
+-#define IRS1125_REG_EFUSEVAL4  0xB0A1
+-#define IRS1125_REG_DMEM_SHADOW        0xC320
++#define IRS1125_REG_SAFE_RECONFIG     0xA850
++#define IRS1125_REG_CSICFG            0xA882
++#define IRS1125_REG_DESIGN_STEP               0xB0AD
++#define IRS1125_REG_EFUSEVAL2         0xB09F
++#define IRS1125_REG_EFUSEVAL3         0xB0A0
++#define IRS1125_REG_EFUSEVAL4         0xB0A1
++#define IRS1125_REG_DMEM_SHADOW               0xC320
+-#define IRS1125_DESIGN_STEP_EXPECTED 0x0a12
++#define IRS1125_DESIGN_STEP_EXPECTED  0x0a12
+ #define IRS1125_ROW_START_DEF         0
+ #define IRS1125_COLUMN_START_DEF      0
+-#define IRS1125_WINDOW_HEIGHT_DEF      288
++#define IRS1125_WINDOW_HEIGHT_DEF     288
+ #define IRS1125_WINDOW_WIDTH_DEF      352
+ struct regval_list {
+@@ -87,7 +89,7 @@ static inline struct irs1125 *to_state(s
+       return container_of(sd, struct irs1125, sd);
+ }
+-static struct regval_list irs1125_26MHz[] = {
++static struct regval_list irs1125_26mhz[] = {
+       {0xB017, 0x0413},
+       {0xB086, 0x3535},
+       {0xB0AE, 0xEF02},
+@@ -153,7 +155,7 @@ static struct regval_list irs1125_26MHz[
+       {0xFFFF, 100}
+ };
+-static struct regval_list irs1125_seq_cfg[] = {
++static struct regval_list irs1125_seq_cfg_init[] = {
+       {0xC3A0, 0x823D},
+       {0xC3A1, 0xB13B},
+       {0xC3A2, 0x0313},
+@@ -243,6 +245,7 @@ static int irs1125_write(struct v4l2_sub
+               dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
+                       __func__, reg);
++      dev_dbg(&client->dev, "write addr 0x%04x, val 0x%04x\n", reg, val);
+       return ret;
+ }
+@@ -364,8 +367,8 @@ static int __sensor_init(struct v4l2_sub
+               cnt++;
+       }
+-      ret = irs1125_write_array(sd, irs1125_26MHz,
+-                                ARRAY_SIZE(irs1125_26MHz));
++      ret = irs1125_write_array(sd, irs1125_26mhz,
++                                ARRAY_SIZE(irs1125_26mhz));
+       if (ret < 0) {
+               dev_err(&client->dev, "write sensor default regs error\n");
+               return ret;
+@@ -415,8 +418,8 @@ static int __sensor_init(struct v4l2_sub
+       }
+       release_firmware(fw);
+-      ret = irs1125_write_array(sd, irs1125_seq_cfg,
+-                                ARRAY_SIZE(irs1125_seq_cfg));
++      ret = irs1125_write_array(sd, irs1125_seq_cfg_init,
++                                ARRAY_SIZE(irs1125_seq_cfg_init));
+       if (ret < 0) {
+               dev_err(&client->dev, "write default sequence failed\n");
+               return ret;
+@@ -1037,6 +1040,7 @@ static int irs1125_probe(struct i2c_clie
+       }
+       gpio_num = desc_to_gpio(sensor->reset);
++      dev_dbg(&client->dev, "reset on GPIO num %d\n", gpio_num);
+       mutex_init(&sensor->lock);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0792-media-irs1125-Atomic-access-to-imager-reconfiguratio.patch b/target/linux/bcm27xx/patches-5.4/950-0792-media-irs1125-Atomic-access-to-imager-reconfiguratio.patch
new file mode 100644 (file)
index 0000000..2b5d4b5
--- /dev/null
@@ -0,0 +1,381 @@
+From 3afb0a757409f5186812b3ea36c61a03855e47d2 Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Tue, 16 Jun 2020 13:31:36 +0200
+Subject: [PATCH] media: irs1125: Atomic access to imager
+ reconfiguration
+
+Instead of changing the exposure and framerate settings for all sequences,
+they can be changed for every sequence individually now. Therefore the
+IRS1125_CID_SAFE_RECONFIG ctrl has been removed and replaced by
+IRS1125_CID_SAFE_RECONFIG_S<seq_num>_EXPO and *_FRAME ctrls.
+
+The consistency check in the sequence ctrl IRS1125_CID_SEQ_CONFIG
+is removed.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ drivers/media/i2c/irs1125.c | 224 ++++++++++++++++++++++++------------
+ drivers/media/i2c/irs1125.h |  68 ++++++++---
+ 2 files changed, 204 insertions(+), 88 deletions(-)
+
+--- a/drivers/media/i2c/irs1125.c
++++ b/drivers/media/i2c/irs1125.c
+@@ -89,6 +89,52 @@ static inline struct irs1125 *to_state(s
+       return container_of(sd, struct irs1125, sd);
+ }
++static const char *expo_ctrl_names[IRS1125_NUM_SEQ_ENTRIES] = {
++      "safe reconfiguration of exposure of sequence 0",
++      "safe reconfiguration of exposure of sequence 1",
++      "safe reconfiguration of exposure of sequence 2",
++      "safe reconfiguration of exposure of sequence 3",
++      "safe reconfiguration of exposure of sequence 4",
++      "safe reconfiguration of exposure of sequence 5",
++      "safe reconfiguration of exposure of sequence 6",
++      "safe reconfiguration of exposure of sequence 7",
++      "safe reconfiguration of exposure of sequence 8",
++      "safe reconfiguration of exposure of sequence 9",
++      "safe reconfiguration of exposure of sequence 10",
++      "safe reconfiguration of exposure of sequence 11",
++      "safe reconfiguration of exposure of sequence 12",
++      "safe reconfiguration of exposure of sequence 13",
++      "safe reconfiguration of exposure of sequence 14",
++      "safe reconfiguration of exposure of sequence 15",
++      "safe reconfiguration of exposure of sequence 16",
++      "safe reconfiguration of exposure of sequence 17",
++      "safe reconfiguration of exposure of sequence 18",
++      "safe reconfiguration of exposure of sequence 19",
++};
++
++static const char *frame_ctrl_names[IRS1125_NUM_SEQ_ENTRIES] = {
++      "safe reconfiguration of framerate of sequence 0",
++      "safe reconfiguration of framerate of sequence 1",
++      "safe reconfiguration of framerate of sequence 2",
++      "safe reconfiguration of framerate of sequence 3",
++      "safe reconfiguration of framerate of sequence 4",
++      "safe reconfiguration of framerate of sequence 5",
++      "safe reconfiguration of framerate of sequence 6",
++      "safe reconfiguration of framerate of sequence 7",
++      "safe reconfiguration of framerate of sequence 8",
++      "safe reconfiguration of framerate of sequence 9",
++      "safe reconfiguration of framerate of sequence 10",
++      "safe reconfiguration of framerate of sequence 11",
++      "safe reconfiguration of framerate of sequence 12",
++      "safe reconfiguration of framerate of sequence 13",
++      "safe reconfiguration of framerate of sequence 14",
++      "safe reconfiguration of framerate of sequence 15",
++      "safe reconfiguration of framerate of sequence 16",
++      "safe reconfiguration of framerate of sequence 17",
++      "safe reconfiguration of framerate of sequence 18",
++      "safe reconfiguration of framerate of sequence 19",
++};
++
+ static struct regval_list irs1125_26mhz[] = {
+       {0xB017, 0x0413},
+       {0xB086, 0x3535},
+@@ -561,36 +607,57 @@ static int irs1125_s_ctrl(struct v4l2_ct
+       struct irs1125 *dev = container_of(ctrl->handler,
+                                       struct irs1125, ctrl_handler);
+       struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
+-      int err, i;
+       struct irs1125_mod_pll *mod_cur, *mod_new;
+-      struct irs1125_seq_cfg *cfg_cur, *cfg_new;
+       u16 addr, val;
+-
+-      err = 0;
++      int err = 0, i;
+       switch (ctrl->id) {
+-      case IRS1125_CID_SAFE_RECONFIG:
+-      {
+-              struct irs1125_illu *illu_cur, *illu_new;
+-
+-              illu_new = (struct irs1125_illu *)ctrl->p_new.p;
+-              illu_cur = (struct irs1125_illu *)ctrl->p_cur.p;
+-              for (i = 0; i < IRS1125_NUM_SEQ_ENTRIES; i++) {
+-                      if (illu_cur[i].exposure != illu_new[i].exposure) {
+-                              addr = 0xA850 + i * 2;
+-                              val = illu_new[i].exposure;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (illu_cur[i].framerate != illu_new[i].framerate) {
+-                              addr = 0xA851 + i * 2;
+-                              val = illu_new[i].framerate;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-              }
++      case IRS1125_CID_SAFE_RECONFIG_S0_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S0_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S1_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S1_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S2_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S2_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S3_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S3_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S4_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S4_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S5_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S5_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S6_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S6_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S7_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S7_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S8_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S8_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S9_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S9_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S10_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S10_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S11_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S11_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S12_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S12_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S13_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S13_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S14_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S14_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S15_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S15_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S16_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S16_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S17_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S17_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S18_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S18_FRAME:
++      case IRS1125_CID_SAFE_RECONFIG_S19_EXPO:
++      case IRS1125_CID_SAFE_RECONFIG_S19_FRAME: {
++              unsigned int offset = ctrl->id -
++                      IRS1125_CID_SAFE_RECONFIG_S0_EXPO;
++
++              err = irs1125_write(&dev->sd,
++                                  IRS1125_REG_SAFE_RECONFIG + offset,
++                                  ctrl->val);
+               break;
+       }
+       case IRS1125_CID_MOD_PLL:
+@@ -655,40 +722,40 @@ static int irs1125_s_ctrl(struct v4l2_ct
+                       }
+               }
+               break;
+-      case IRS1125_CID_SEQ_CONFIG:
++      case IRS1125_CID_SEQ_CONFIG: {
++              struct irs1125_seq_cfg *cfg_new;
++
+               cfg_new = (struct irs1125_seq_cfg *)ctrl->p_new.p;
+-              cfg_cur = (struct irs1125_seq_cfg *)ctrl->p_cur.p;
+               for (i = 0; i < IRS1125_NUM_SEQ_ENTRIES; i++) {
+-                      if (cfg_cur[i].exposure != cfg_new[i].exposure) {
+-                              addr = IRS1125_REG_DMEM_SHADOW + i * 4;
+-                              val = cfg_new[i].exposure;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (cfg_cur[i].framerate != cfg_new[i].framerate) {
+-                              addr = IRS1125_REG_DMEM_SHADOW + 1 + i * 4;
+-                              val = cfg_new[i].framerate;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (cfg_cur[i].ps != cfg_new[i].ps) {
+-                              addr = IRS1125_REG_DMEM_SHADOW + 2 + i * 4;
+-                              val = cfg_new[i].ps;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (cfg_cur[i].pll != cfg_new[i].pll) {
+-                              addr = IRS1125_REG_DMEM_SHADOW + 3 + i * 4;
+-                              val = cfg_new[i].pll;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
++                      unsigned int seq_offset = i * 4;
++                      u16 addr, val;
++
++                      addr = IRS1125_REG_DMEM_SHADOW + seq_offset;
++                      val = cfg_new[i].exposure;
++                      err = irs1125_write(&dev->sd, addr, val);
++                      if (err < 0)
++                              break;
++
++                      addr = IRS1125_REG_DMEM_SHADOW + 1 + seq_offset;
++                      val = cfg_new[i].framerate;
++                      err = irs1125_write(&dev->sd, addr, val);
++                      if (err < 0)
++                              break;
++
++                      addr = IRS1125_REG_DMEM_SHADOW + 2 + seq_offset;
++                      val = cfg_new[i].ps;
++                      err = irs1125_write(&dev->sd, addr, val);
++                      if (err < 0)
++                              break;
++
++                      addr = IRS1125_REG_DMEM_SHADOW + 3 + seq_offset;
++                      val = cfg_new[i].pll;
++                      err = irs1125_write(&dev->sd, addr, val);
++                      if (err < 0)
++                              break;
+               }
+               break;
++      }
+       case IRS1125_CID_NUM_SEQS:
+               err = irs1125_write(&dev->sd, 0xA88D, ctrl->val - 1);
+               if (err >= 0)
+@@ -760,19 +827,6 @@ static const struct v4l2_ctrl_config irs
+                       IRS1125_NUM_MOD_PLLS}
+       }, {
+               .ops = &irs1125_ctrl_ops,
+-              .id = IRS1125_CID_SAFE_RECONFIG,
+-              .name = "Change exposure and pause of single seq",
+-              .type = V4L2_CTRL_TYPE_U16,
+-              .flags = V4L2_CTRL_FLAG_HAS_PAYLOAD,
+-              .min = 0,
+-              .max = U16_MAX,
+-              .step = 1,
+-              .def = 0,
+-              .elem_size = sizeof(u16),
+-              .dims = {sizeof(struct irs1125_illu) / sizeof(u16),
+-                      IRS1125_NUM_SEQ_ENTRIES}
+-      }, {
+-              .ops = &irs1125_ctrl_ops,
+               .id = IRS1125_CID_SEQ_CONFIG,
+               .name = "Change sequence settings",
+               .type = V4L2_CTRL_TYPE_U16,
+@@ -900,9 +954,16 @@ static int irs1125_ctrls_init(struct irs
+ {
+       struct v4l2_ctrl *ctrl;
+       int err, i;
+-      struct v4l2_ctrl_handler *hdl;
++      struct v4l2_ctrl_handler *hdl = &sensor->ctrl_handler;
++      struct v4l2_ctrl_config ctrl_cfg = {
++              .ops = &irs1125_ctrl_ops,
++              .type = V4L2_CTRL_TYPE_INTEGER,
++              .min = 0,
++              .max = U16_MAX,
++              .step = 1,
++              .def = 0x1000
++      };
+-      hdl = &sensor->ctrl_handler;
+       v4l2_ctrl_handler_init(hdl, ARRAY_SIZE(irs1125_custom_ctrls));
+       for (i = 0; i < ARRAY_SIZE(irs1125_custom_ctrls); i++)  {
+@@ -923,6 +984,27 @@ static int irs1125_ctrls_init(struct irs
+               goto error_ctrls;
+       }
++      for (i = 0; i < IRS1125_NUM_SEQ_ENTRIES; i++) {
++              ctrl_cfg.name = expo_ctrl_names[i];
++              ctrl_cfg.id = IRS1125_CID_SAFE_RECONFIG_S0_EXPO + i * 2;
++              ctrl = v4l2_ctrl_new_custom(hdl, &ctrl_cfg,
++                                          NULL);
++              if (!ctrl)
++                      dev_err(dev, "Failed to init exposure control %s\n",
++                              ctrl_cfg.name);
++      }
++
++      ctrl_cfg.def = 0;
++      for (i = 0; i < IRS1125_NUM_SEQ_ENTRIES; i++) {
++              ctrl_cfg.name = frame_ctrl_names[i];
++              ctrl_cfg.id = IRS1125_CID_SAFE_RECONFIG_S0_FRAME + i * 2;
++              ctrl = v4l2_ctrl_new_custom(hdl, &ctrl_cfg,
++                                          NULL);
++              if (!ctrl)
++                      dev_err(dev, "Failed to init framerate control %s\n",
++                              ctrl_cfg.name);
++      }
++
+       sensor->sd.ctrl_handler = hdl;
+       return 0;
+--- a/drivers/media/i2c/irs1125.h
++++ b/drivers/media/i2c/irs1125.h
+@@ -21,18 +21,57 @@
+ #define IRS1125_NUM_SEQ_ENTRIES 20
+ #define IRS1125_NUM_MOD_PLLS 4
+-#define IRS1125_CID_CUSTOM_BASE        (V4L2_CID_USER_BASE | 0xf000)
+-#define IRS1125_CID_SAFE_RECONFIG      (IRS1125_CID_CUSTOM_BASE + 0)
+-#define IRS1125_CID_CONTINUOUS_TRIG    (IRS1125_CID_CUSTOM_BASE + 1)
+-#define IRS1125_CID_TRIGGER            (IRS1125_CID_CUSTOM_BASE + 2)
+-#define IRS1125_CID_RECONFIG           (IRS1125_CID_CUSTOM_BASE + 3)
+-#define IRS1125_CID_ILLU_ON            (IRS1125_CID_CUSTOM_BASE + 4)
+-#define IRS1125_CID_NUM_SEQS           (IRS1125_CID_CUSTOM_BASE + 5)
+-#define IRS1125_CID_MOD_PLL            (IRS1125_CID_CUSTOM_BASE + 6)
+-#define IRS1125_CID_SEQ_CONFIG         (IRS1125_CID_CUSTOM_BASE + 7)
+-#define IRS1125_CID_IDENT0             (IRS1125_CID_CUSTOM_BASE + 8)
+-#define IRS1125_CID_IDENT1             (IRS1125_CID_CUSTOM_BASE + 9)
+-#define IRS1125_CID_IDENT2             (IRS1125_CID_CUSTOM_BASE + 10)
++#define IRS1125_CID_CUSTOM_BASE                       (V4L2_CID_USER_BASE | 0xf000)
++#define IRS1125_CID_CONTINUOUS_TRIG           (IRS1125_CID_CUSTOM_BASE + 1)
++#define IRS1125_CID_TRIGGER                   (IRS1125_CID_CUSTOM_BASE + 2)
++#define IRS1125_CID_RECONFIG                  (IRS1125_CID_CUSTOM_BASE + 3)
++#define IRS1125_CID_ILLU_ON                   (IRS1125_CID_CUSTOM_BASE + 4)
++#define IRS1125_CID_NUM_SEQS                  (IRS1125_CID_CUSTOM_BASE + 5)
++#define IRS1125_CID_MOD_PLL                   (IRS1125_CID_CUSTOM_BASE + 6)
++#define IRS1125_CID_SEQ_CONFIG                        (IRS1125_CID_CUSTOM_BASE + 7)
++#define IRS1125_CID_IDENT0                    (IRS1125_CID_CUSTOM_BASE + 8)
++#define IRS1125_CID_IDENT1                    (IRS1125_CID_CUSTOM_BASE + 9)
++#define IRS1125_CID_IDENT2                    (IRS1125_CID_CUSTOM_BASE + 10)
++#define IRS1125_CID_SAFE_RECONFIG_S0_EXPO     (IRS1125_CID_CUSTOM_BASE + 11)
++#define IRS1125_CID_SAFE_RECONFIG_S0_FRAME    (IRS1125_CID_CUSTOM_BASE + 12)
++#define IRS1125_CID_SAFE_RECONFIG_S1_EXPO     (IRS1125_CID_CUSTOM_BASE + 13)
++#define IRS1125_CID_SAFE_RECONFIG_S1_FRAME    (IRS1125_CID_CUSTOM_BASE + 14)
++#define IRS1125_CID_SAFE_RECONFIG_S2_EXPO     (IRS1125_CID_CUSTOM_BASE + 15)
++#define IRS1125_CID_SAFE_RECONFIG_S2_FRAME    (IRS1125_CID_CUSTOM_BASE + 16)
++#define IRS1125_CID_SAFE_RECONFIG_S3_EXPO     (IRS1125_CID_CUSTOM_BASE + 17)
++#define IRS1125_CID_SAFE_RECONFIG_S3_FRAME    (IRS1125_CID_CUSTOM_BASE + 18)
++#define IRS1125_CID_SAFE_RECONFIG_S4_EXPO     (IRS1125_CID_CUSTOM_BASE + 19)
++#define IRS1125_CID_SAFE_RECONFIG_S4_FRAME    (IRS1125_CID_CUSTOM_BASE + 20)
++#define IRS1125_CID_SAFE_RECONFIG_S5_EXPO     (IRS1125_CID_CUSTOM_BASE + 21)
++#define IRS1125_CID_SAFE_RECONFIG_S5_FRAME    (IRS1125_CID_CUSTOM_BASE + 22)
++#define IRS1125_CID_SAFE_RECONFIG_S6_EXPO     (IRS1125_CID_CUSTOM_BASE + 23)
++#define IRS1125_CID_SAFE_RECONFIG_S6_FRAME    (IRS1125_CID_CUSTOM_BASE + 24)
++#define IRS1125_CID_SAFE_RECONFIG_S7_EXPO     (IRS1125_CID_CUSTOM_BASE + 25)
++#define IRS1125_CID_SAFE_RECONFIG_S7_FRAME    (IRS1125_CID_CUSTOM_BASE + 26)
++#define IRS1125_CID_SAFE_RECONFIG_S8_EXPO     (IRS1125_CID_CUSTOM_BASE + 27)
++#define IRS1125_CID_SAFE_RECONFIG_S8_FRAME    (IRS1125_CID_CUSTOM_BASE + 28)
++#define IRS1125_CID_SAFE_RECONFIG_S9_EXPO     (IRS1125_CID_CUSTOM_BASE + 29)
++#define IRS1125_CID_SAFE_RECONFIG_S9_FRAME    (IRS1125_CID_CUSTOM_BASE + 30)
++#define IRS1125_CID_SAFE_RECONFIG_S10_EXPO    (IRS1125_CID_CUSTOM_BASE + 31)
++#define IRS1125_CID_SAFE_RECONFIG_S10_FRAME   (IRS1125_CID_CUSTOM_BASE + 32)
++#define IRS1125_CID_SAFE_RECONFIG_S11_EXPO    (IRS1125_CID_CUSTOM_BASE + 33)
++#define IRS1125_CID_SAFE_RECONFIG_S11_FRAME   (IRS1125_CID_CUSTOM_BASE + 34)
++#define IRS1125_CID_SAFE_RECONFIG_S12_EXPO    (IRS1125_CID_CUSTOM_BASE + 35)
++#define IRS1125_CID_SAFE_RECONFIG_S12_FRAME   (IRS1125_CID_CUSTOM_BASE + 36)
++#define IRS1125_CID_SAFE_RECONFIG_S13_EXPO    (IRS1125_CID_CUSTOM_BASE + 37)
++#define IRS1125_CID_SAFE_RECONFIG_S13_FRAME   (IRS1125_CID_CUSTOM_BASE + 38)
++#define IRS1125_CID_SAFE_RECONFIG_S14_EXPO    (IRS1125_CID_CUSTOM_BASE + 39)
++#define IRS1125_CID_SAFE_RECONFIG_S14_FRAME   (IRS1125_CID_CUSTOM_BASE + 40)
++#define IRS1125_CID_SAFE_RECONFIG_S15_EXPO    (IRS1125_CID_CUSTOM_BASE + 41)
++#define IRS1125_CID_SAFE_RECONFIG_S15_FRAME   (IRS1125_CID_CUSTOM_BASE + 42)
++#define IRS1125_CID_SAFE_RECONFIG_S16_EXPO    (IRS1125_CID_CUSTOM_BASE + 43)
++#define IRS1125_CID_SAFE_RECONFIG_S16_FRAME   (IRS1125_CID_CUSTOM_BASE + 44)
++#define IRS1125_CID_SAFE_RECONFIG_S17_EXPO    (IRS1125_CID_CUSTOM_BASE + 45)
++#define IRS1125_CID_SAFE_RECONFIG_S17_FRAME   (IRS1125_CID_CUSTOM_BASE + 46)
++#define IRS1125_CID_SAFE_RECONFIG_S18_EXPO    (IRS1125_CID_CUSTOM_BASE + 47)
++#define IRS1125_CID_SAFE_RECONFIG_S18_FRAME   (IRS1125_CID_CUSTOM_BASE + 48)
++#define IRS1125_CID_SAFE_RECONFIG_S19_EXPO    (IRS1125_CID_CUSTOM_BASE + 49)
++#define IRS1125_CID_SAFE_RECONFIG_S19_FRAME   (IRS1125_CID_CUSTOM_BASE + 50)
+ struct irs1125_seq_cfg {
+       __u16 exposure;
+@@ -41,11 +80,6 @@ struct irs1125_seq_cfg {
+       __u16 pll;
+ };
+-struct irs1125_illu {
+-      __u16 exposure;
+-      __u16 framerate;
+-};
+-
+ struct irs1125_mod_pll {
+       __u16 pllcfg1;
+       __u16 pllcfg2;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch b/target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch
new file mode 100644 (file)
index 0000000..9e9b272
--- /dev/null
@@ -0,0 +1,181 @@
+From be2df6c864ba668364011301530372f5b8798593 Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Tue, 16 Jun 2020 13:33:56 +0200
+Subject: [PATCH] media: irs1125: Keep HW in sync after imager reset
+
+When closing the video device, the irs1125 is put in power down state.
+To keep V4L2 ctrls and the HW in sync, v4l2_ctrl_handler_setup is
+called after power up.
+
+The compound ctrl IRS1125_CID_MOD_PLL however has a default value
+of all zeros, which puts the imager into a non responding state.
+Thus, this ctrl is not written by the driver into HW after power up.
+The userspace has to take care to write senseful data.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ drivers/media/i2c/irs1125.c | 121 +++++++++++++++++-------------------
+ 1 file changed, 58 insertions(+), 63 deletions(-)
+
+--- a/drivers/media/i2c/irs1125.c
++++ b/drivers/media/i2c/irs1125.c
+@@ -82,6 +82,7 @@ struct irs1125 {
+       struct v4l2_ctrl *ctrl_numseq;
+       int power_count;
++      bool mod_pll_init;
+ };
+ static inline struct irs1125 *to_state(struct v4l2_subdev *sd)
+@@ -276,8 +277,7 @@ static struct regval_list irs1125_seq_cf
+       {0xC039, 0x0000},
+       {0xC401, 0x0002},
+-      {0xFFFF, 1},
+-      {0xA87C, 0x0001}
++      {0xFFFF, 1}
+ };
+ static int irs1125_write(struct v4l2_subdev *sd, u16 reg, u16 val)
+@@ -471,7 +471,11 @@ static int __sensor_init(struct v4l2_sub
+               return ret;
+       }
+-      return 0;
++      irs1125->mod_pll_init = true;
++      v4l2_ctrl_handler_setup(&irs1125->ctrl_handler);
++      irs1125->mod_pll_init = false;
++
++      return irs1125_write(sd, 0xA87C, 0x0001);
+ }
+ static int irs1125_sensor_power(struct v4l2_subdev *sd, int on)
+@@ -607,8 +611,6 @@ static int irs1125_s_ctrl(struct v4l2_ct
+       struct irs1125 *dev = container_of(ctrl->handler,
+                                       struct irs1125, ctrl_handler);
+       struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
+-      struct irs1125_mod_pll *mod_cur, *mod_new;
+-      u16 addr, val;
+       int err = 0, i;
+       switch (ctrl->id) {
+@@ -660,68 +662,61 @@ static int irs1125_s_ctrl(struct v4l2_ct
+                                   ctrl->val);
+               break;
+       }
+-      case IRS1125_CID_MOD_PLL:
++      case IRS1125_CID_MOD_PLL: {
++              struct irs1125_mod_pll *mod_new;
++
++              if (dev->mod_pll_init)
++                      break;
++
+               mod_new = (struct irs1125_mod_pll *)ctrl->p_new.p;
+-              mod_cur = (struct irs1125_mod_pll *)ctrl->p_cur.p;
+               for (i = 0; i < IRS1125_NUM_MOD_PLLS; i++) {
+-                      if (mod_cur[i].pllcfg1 != mod_new[i].pllcfg1) {
+-                              addr = 0xC3A0 + i * 3;
+-                              val = mod_new[i].pllcfg1;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg2 != mod_new[i].pllcfg2) {
+-                              addr = 0xC3A1 + i * 3;
+-                              val = mod_new[i].pllcfg2;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg3 != mod_new[i].pllcfg3) {
+-                              addr = 0xC3A2 + i * 3;
+-                              val = mod_new[i].pllcfg3;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg4 != mod_new[i].pllcfg4) {
+-                              addr = 0xC24C + i * 5;
+-                              val = mod_new[i].pllcfg4;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg5 != mod_new[i].pllcfg5) {
+-                              addr = 0xC24D + i * 5;
+-                              val = mod_new[i].pllcfg5;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg6 != mod_new[i].pllcfg6) {
+-                              addr = 0xC24E + i * 5;
+-                              val = mod_new[i].pllcfg6;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg7 != mod_new[i].pllcfg7) {
+-                              addr = 0xC24F + i * 5;
+-                              val = mod_new[i].pllcfg7;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
+-                      if (mod_cur[i].pllcfg8 != mod_new[i].pllcfg8) {
+-                              addr = 0xC250 + i * 5;
+-                              val = mod_new[i].pllcfg8;
+-                              err = irs1125_write(&dev->sd, addr, val);
+-                              if (err < 0)
+-                                      break;
+-                      }
++                      unsigned int pll_offset, ssc_offset;
++
++                      pll_offset = i * 3;
++                      ssc_offset = i * 5;
++
++                      err = irs1125_write(&dev->sd, 0xC3A0 + pll_offset,
++                                          mod_new[i].pllcfg1);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC3A1 + pll_offset,
++                                          mod_new[i].pllcfg2);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC3A2 + pll_offset,
++                                          mod_new[i].pllcfg3);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC24C + ssc_offset,
++                                          mod_new[i].pllcfg4);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC24D + ssc_offset,
++                                          mod_new[i].pllcfg5);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC24E + ssc_offset,
++                                          mod_new[i].pllcfg6);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC24F + ssc_offset,
++                                          mod_new[i].pllcfg7);
++                      if (err < 0)
++                              break;
++
++                      err = irs1125_write(&dev->sd, 0xC250 + ssc_offset,
++                                          mod_new[i].pllcfg8);
++                      if (err < 0)
++                              break;
+               }
+               break;
++      }
+       case IRS1125_CID_SEQ_CONFIG: {
+               struct irs1125_seq_cfg *cfg_new;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0794-staging-bcm2835-audio-Add-missing-MODULE_ALIAS.patch b/target/linux/bcm27xx/patches-5.4/950-0794-staging-bcm2835-audio-Add-missing-MODULE_ALIAS.patch
new file mode 100644 (file)
index 0000000..5e09644
--- /dev/null
@@ -0,0 +1,30 @@
+From 1f7c929fc7b010ceca45f8b91b22e71e697b6ec7 Mon Sep 17 00:00:00 2001
+From: Maxim Mikityanskiy <maxtram95@gmail.com>
+Date: Sat, 20 Jun 2020 15:40:00 +0300
+Subject: [PATCH] staging: bcm2835-audio: Add missing MODULE_ALIAS
+
+Commit 8353fe6f1e0f ("Revert "staging: bcm2835-audio: Drop DT
+dependency"") reverts the upstream change and makes bcm2835-audio use
+device tree again, however, it also removes the MODULE_ALIAS for the
+platform device. This MODULE_ALIAS is needed, because VCHIQ registers
+bcm2835-audio as a child platform device since commit 25c7597af20d
+("staging: vchiq_arm: Register a platform device for audio"), and this
+mechanism is adopted also in the downstream kernel.
+
+This commit puts back that MODULE_ALIAS to make bcm2835-audio
+autoprobing work again. The rest of VCHIQ children have their
+MODULE_ALIASes in place.
+
+Fixes: 8353fe6f1e0f ("Revert "staging: bcm2835-audio: Drop DT dependency"")
+Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -438,3 +438,4 @@ module_platform_driver(bcm2835_alsa_driv
+ MODULE_AUTHOR("Dom Cobley");
+ MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bcm2835_audio");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0795-media-v4l2-subdev-Introduce-get-set-_mbus_config-pad.patch b/target/linux/bcm27xx/patches-5.4/950-0795-media-v4l2-subdev-Introduce-get-set-_mbus_config-pad.patch
new file mode 100644 (file)
index 0000000..9108284
--- /dev/null
@@ -0,0 +1,63 @@
+From 487203abdef24b7d3cdd110f1b1e699fd22aa02c Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:36 +0200
+Subject: [PATCH]_mbus_config
+ pad ops
+
+Upstream https://patchwork.linuxtv.org/patch/64669/
+
+Introduce two new pad operations to allow retrieving and configuring the
+media bus parameters on a subdevice pad.
+
+The newly introduced operations aims to replace the s/g_mbus_config video
+operations, which have been on their way for deprecation since a long
+time.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ include/media/v4l2-subdev.h | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -670,6 +670,29 @@ struct v4l2_subdev_pad_config {
+  *
+  * @set_frame_desc: set the low level media bus frame parameters, @fd array
+  *                  may be adjusted by the subdev driver to device capabilities.
++ *
++ * @get_mbus_config: get the media bus configuration of a remote sub-device.
++ *                 The media bus configuration is usually retrieved from the
++ *                 firmware interface at sub-device probe time, immediately
++ *                 applied to the hardware and eventually adjusted by the
++ *                 driver. Remote sub-devices (usually video receivers) shall
++ *                 use this operation to query the transmitting end bus
++ *                 configuration in order to adjust their own one accordingly.
++ *                 Callers should make sure they get the most up-to-date as
++ *                 possible configuration from the remote end, likely calling
++ *                 this operation as close as possible to stream on time. The
++ *                 operation shall fail if the pad index it has been called on
++ *                 is not valid.
++ *
++ * @set_mbus_config: set the media bus configuration of a remote sub-device.
++ *                 This operations is intended to allow, in combination with
++ *                 the get_mbus_config operation, the negotiation of media bus
++ *                 configuration parameters between media sub-devices. The
++ *                 operation shall not fail if the requested configuration is
++ *                 not supported, but the driver shall update the content of
++ *                 the %config argument to reflect what has been actually
++ *                 applied to the hardware. The operation shall fail if the
++ *                 pad index it has been called on is not valid.
+  */
+ struct v4l2_subdev_pad_ops {
+       int (*init_cfg)(struct v4l2_subdev *sd,
+@@ -710,6 +733,10 @@ struct v4l2_subdev_pad_ops {
+                             struct v4l2_mbus_frame_desc *fd);
+       int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
++      int (*get_mbus_config)(struct v4l2_subdev *sd, unsigned int pad,
++                             struct v4l2_mbus_config *config);
++      int (*set_mbus_config)(struct v4l2_subdev *sd, unsigned int pad,
++                             struct v4l2_mbus_config *config);
+ };
+ /**
diff --git a/target/linux/bcm27xx/patches-5.4/950-0796-media-i2c-Use-the-new-get_mbus_config-pad-op.patch b/target/linux/bcm27xx/patches-5.4/950-0796-media-i2c-Use-the-new-get_mbus_config-pad-op.patch
new file mode 100644 (file)
index 0000000..5c432d0
--- /dev/null
@@ -0,0 +1,235 @@
+From 87fde70ab0ba99860153b127e6821be5ae74e73b Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:37 +0200
+Subject: [PATCH] media: i2c: Use the new get_mbus_config pad op
+
+Upstream https://patchwork.linuxtv.org/patch/64669/
+
+Move the existing users of the g_mbus_config video operation to use the
+newly introduced get_mbus_config pad operations.
+
+All the ported drivers report a static media bus configuration and do no
+support s_mbus_config so the operation implementation has not changed.
+
+Bridge drivers needs to call the new pad operation and will receive an
+-ENOICTLCMD when calling the old g_mbus_config video operation
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/i2c/adv7180.c   | 7 ++++---
+ drivers/media/i2c/ml86v7667.c | 7 ++++---
+ drivers/media/i2c/mt9m001.c   | 7 ++++---
+ drivers/media/i2c/mt9m111.c   | 7 ++++---
+ drivers/media/i2c/ov9640.c    | 7 ++++---
+ drivers/media/i2c/tc358743.c  | 7 ++++---
+ drivers/media/i2c/tvp5150.c   | 7 ++++---
+ 7 files changed, 28 insertions(+), 21 deletions(-)
+
+--- a/drivers/media/i2c/adv7180.c
++++ b/drivers/media/i2c/adv7180.c
+@@ -749,8 +749,9 @@ static int adv7180_set_pad_format(struct
+       return ret;
+ }
+-static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
+-                               struct v4l2_mbus_config *cfg)
++static int adv7180_get_mbus_config(struct v4l2_subdev *sd,
++                                 unsigned int pad,
++                                 struct v4l2_mbus_config *cfg)
+ {
+       struct adv7180_state *state = to_state(sd);
+@@ -841,7 +842,6 @@ static const struct v4l2_subdev_video_op
+       .querystd = adv7180_querystd,
+       .g_input_status = adv7180_g_input_status,
+       .s_routing = adv7180_s_routing,
+-      .g_mbus_config = adv7180_g_mbus_config,
+       .g_pixelaspect = adv7180_g_pixelaspect,
+       .g_tvnorms = adv7180_g_tvnorms,
+       .s_stream = adv7180_s_stream,
+@@ -857,6 +857,7 @@ static const struct v4l2_subdev_pad_ops
+       .enum_mbus_code = adv7180_enum_mbus_code,
+       .set_fmt = adv7180_set_pad_format,
+       .get_fmt = adv7180_get_pad_format,
++      .get_mbus_config = adv7180_get_mbus_config,
+ };
+ static const struct v4l2_subdev_sensor_ops adv7180_sensor_ops = {
+--- a/drivers/media/i2c/ml86v7667.c
++++ b/drivers/media/i2c/ml86v7667.c
+@@ -219,8 +219,9 @@ static int ml86v7667_fill_fmt(struct v4l
+       return 0;
+ }
+-static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd,
+-                                 struct v4l2_mbus_config *cfg)
++static int ml86v7667_get_mbus_config(struct v4l2_subdev *sd,
++                                   unsigned int pad,
++                                   struct v4l2_mbus_config *cfg)
+ {
+       cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+                    V4L2_MBUS_DATA_ACTIVE_HIGH;
+@@ -291,13 +292,13 @@ static const struct v4l2_subdev_video_op
+       .s_std = ml86v7667_s_std,
+       .querystd = ml86v7667_querystd,
+       .g_input_status = ml86v7667_g_input_status,
+-      .g_mbus_config = ml86v7667_g_mbus_config,
+ };
+ static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = {
+       .enum_mbus_code = ml86v7667_enum_mbus_code,
+       .get_fmt = ml86v7667_fill_fmt,
+       .set_fmt = ml86v7667_fill_fmt,
++      .get_mbus_config = ml86v7667_get_mbus_config,
+ };
+ static const struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = {
+--- a/drivers/media/i2c/mt9m001.c
++++ b/drivers/media/i2c/mt9m001.c
+@@ -689,8 +689,9 @@ static int mt9m001_enum_mbus_code(struct
+       return 0;
+ }
+-static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
+-                              struct v4l2_mbus_config *cfg)
++static int mt9m001_get_mbus_config(struct v4l2_subdev *sd,
++                                 unsigned int pad,
++                                 struct v4l2_mbus_config *cfg)
+ {
+       /* MT9M001 has all capture_format parameters fixed */
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+@@ -703,7 +704,6 @@ static int mt9m001_g_mbus_config(struct
+ static const struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
+       .s_stream       = mt9m001_s_stream,
+-      .g_mbus_config  = mt9m001_g_mbus_config,
+ };
+ static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
+@@ -717,6 +717,7 @@ static const struct v4l2_subdev_pad_ops
+       .set_selection  = mt9m001_set_selection,
+       .get_fmt        = mt9m001_get_fmt,
+       .set_fmt        = mt9m001_set_fmt,
++      .get_mbus_config = mt9m001_get_mbus_config,
+ };
+ static const struct v4l2_subdev_ops mt9m001_subdev_ops = {
+--- a/drivers/media/i2c/mt9m111.c
++++ b/drivers/media/i2c/mt9m111.c
+@@ -1137,8 +1137,9 @@ static int mt9m111_init_cfg(struct v4l2_
+       return 0;
+ }
+-static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
+-                              struct v4l2_mbus_config *cfg)
++static int mt9m111_get_mbus_config(struct v4l2_subdev *sd,
++                                 unsigned int pad,
++                                 struct v4l2_mbus_config *cfg)
+ {
+       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+@@ -1155,7 +1156,6 @@ static int mt9m111_g_mbus_config(struct
+ }
+ static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
+-      .g_mbus_config  = mt9m111_g_mbus_config,
+       .s_stream       = mt9m111_s_stream,
+       .g_frame_interval = mt9m111_g_frame_interval,
+       .s_frame_interval = mt9m111_s_frame_interval,
+@@ -1168,6 +1168,7 @@ static const struct v4l2_subdev_pad_ops
+       .set_selection  = mt9m111_set_selection,
+       .get_fmt        = mt9m111_get_fmt,
+       .set_fmt        = mt9m111_set_fmt,
++      .get_mbus_config = mt9m111_get_mbus_config,
+ };
+ static const struct v4l2_subdev_ops mt9m111_subdev_ops = {
+--- a/drivers/media/i2c/ov9640.c
++++ b/drivers/media/i2c/ov9640.c
+@@ -648,8 +648,9 @@ static const struct v4l2_subdev_core_ops
+ };
+ /* Request bus settings on camera side */
+-static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
+-                              struct v4l2_mbus_config *cfg)
++static int ov9640_get_mbus_config(struct v4l2_subdev *sd,
++                                unsigned int pad,
++                                struct v4l2_mbus_config *cfg)
+ {
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+@@ -661,13 +662,13 @@ static int ov9640_g_mbus_config(struct v
+ static const struct v4l2_subdev_video_ops ov9640_video_ops = {
+       .s_stream       = ov9640_s_stream,
+-      .g_mbus_config  = ov9640_g_mbus_config,
+ };
+ static const struct v4l2_subdev_pad_ops ov9640_pad_ops = {
+       .enum_mbus_code = ov9640_enum_mbus_code,
+       .get_selection  = ov9640_get_selection,
+       .set_fmt        = ov9640_set_fmt,
++      .get_mbus_config = ov9640_get_mbus_config,
+ };
+ static const struct v4l2_subdev_ops ov9640_subdev_ops = {
+--- a/drivers/media/i2c/tc358743.c
++++ b/drivers/media/i2c/tc358743.c
+@@ -1621,8 +1621,9 @@ static int tc358743_dv_timings_cap(struc
+       return 0;
+ }
+-static int tc358743_g_mbus_config(struct v4l2_subdev *sd,
+-                           struct v4l2_mbus_config *cfg)
++static int tc358743_get_mbus_config(struct v4l2_subdev *sd,
++                                  unsigned int pad,
++                                  struct v4l2_mbus_config *cfg)
+ {
+       struct tc358743_state *state = to_state(sd);
+       const u32 mask = V4L2_MBUS_CSI2_LANE_MASK;
+@@ -1852,7 +1853,6 @@ static const struct v4l2_subdev_video_op
+       .s_dv_timings = tc358743_s_dv_timings,
+       .g_dv_timings = tc358743_g_dv_timings,
+       .query_dv_timings = tc358743_query_dv_timings,
+-      .g_mbus_config = tc358743_g_mbus_config,
+       .s_stream = tc358743_s_stream,
+ };
+@@ -1864,6 +1864,7 @@ static const struct v4l2_subdev_pad_ops
+       .set_edid = tc358743_s_edid,
+       .enum_dv_timings = tc358743_enum_dv_timings,
+       .dv_timings_cap = tc358743_dv_timings_cap,
++      .get_mbus_config = tc358743_get_mbus_config,
+ };
+ static const struct v4l2_subdev_ops tc358743_ops = {
+--- a/drivers/media/i2c/tvp5150.c
++++ b/drivers/media/i2c/tvp5150.c
+@@ -1104,8 +1104,9 @@ static int tvp5150_get_selection(struct
+       }
+ }
+-static int tvp5150_g_mbus_config(struct v4l2_subdev *sd,
+-                               struct v4l2_mbus_config *cfg)
++static int tvp5150_get_mbus_config(struct v4l2_subdev *sd,
++                                 unsigned int pad,
++                                 struct v4l2_mbus_config *cfg)
+ {
+       struct tvp5150 *decoder = to_tvp5150(sd);
+@@ -1411,7 +1412,6 @@ static const struct v4l2_subdev_video_op
+       .querystd = tvp5150_querystd,
+       .s_stream = tvp5150_s_stream,
+       .s_routing = tvp5150_s_routing,
+-      .g_mbus_config = tvp5150_g_mbus_config,
+ };
+ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
+@@ -1429,6 +1429,7 @@ static const struct v4l2_subdev_pad_ops
+       .get_fmt = tvp5150_fill_fmt,
+       .get_selection = tvp5150_get_selection,
+       .set_selection = tvp5150_set_selection,
++      .get_mbus_config = tvp5150_get_mbus_config,
+ };
+ static const struct v4l2_subdev_ops tvp5150_ops = {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0797-media-i2c-ov6650-Use-new-get-set-_mbus_config-ops.patch b/target/linux/bcm27xx/patches-5.4/950-0797-media-i2c-ov6650-Use-new-get-set-_mbus_config-ops.patch
new file mode 100644 (file)
index 0000000..d1c0a65
--- /dev/null
@@ -0,0 +1,134 @@
+From 0dd7e12bb7dc81e09440f3330465c31349497dc3 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:38 +0200
+Subject: [PATCH]_mbus_config
+ ops
+
+Upstream https://patchwork.linuxtv.org/patch/64674/
+
+Use the new get_mbus_config and set_mbus_config pad operations in place
+of the video operations currently in use.
+
+Compared to other drivers where the same conversion has been performed,
+ov6650 proved to be a bit more tricky, as the existing g_mbus_config
+implementation did not report the currently applied configuration but
+the set of all possible configuration options.
+
+Adapt the driver to support the semantic of the two newly introduced
+operations:
+- get_mbus_config reports the current media bus configuration
+- set_mbus_config applies only changes explicitly requested and updates
+  the provided cfg parameter to report what has actually been applied to
+  the hardware.
+
+Compile-tested only.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/i2c/ov6650.c | 56 ++++++++++++++++++++++++++------------
+ 1 file changed, 39 insertions(+), 17 deletions(-)
+
+--- a/drivers/media/i2c/ov6650.c
++++ b/drivers/media/i2c/ov6650.c
+@@ -909,46 +909,68 @@ static const struct v4l2_subdev_core_ops
+ };
+ /* Request bus settings on camera side */
+-static int ov6650_g_mbus_config(struct v4l2_subdev *sd,
+-                              struct v4l2_mbus_config *cfg)
++static int ov6650_get_mbus_config(struct v4l2_subdev *sd,
++                                unsigned int pad,
++                                struct v4l2_mbus_config *cfg)
+ {
++      struct i2c_client *client = v4l2_get_subdevdata(sd);
++      u8 comj, comf;
++      int ret;
++
++      ret = ov6650_reg_read(client, REG_COMJ, &comj);
++      if (ret)
++              return ret;
++
++      ret = ov6650_reg_read(client, REG_COMF, &comf);
++      if (ret)
++              return ret;
+-      cfg->flags = V4L2_MBUS_MASTER |
+-              V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+-              V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+-              V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+-              V4L2_MBUS_DATA_ACTIVE_HIGH;
++      cfg->flags = V4L2_MBUS_MASTER
++                 | ((comj & COMJ_VSYNC_HIGH)  ? V4L2_MBUS_VSYNC_ACTIVE_HIGH
++                                              : V4L2_MBUS_VSYNC_ACTIVE_LOW)
++                 | ((comf & COMF_HREF_LOW)    ? V4L2_MBUS_HSYNC_ACTIVE_LOW
++                                              : V4L2_MBUS_HSYNC_ACTIVE_HIGH)
++                 | ((comj & COMJ_PCLK_RISING) ? V4L2_MBUS_PCLK_SAMPLE_RISING
++                                              : V4L2_MBUS_PCLK_SAMPLE_FALLING);
+       cfg->type = V4L2_MBUS_PARALLEL;
+       return 0;
+ }
+ /* Alter bus settings on camera side */
+-static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
+-                              const struct v4l2_mbus_config *cfg)
++static int ov6650_set_mbus_config(struct v4l2_subdev *sd,
++                                unsigned int pad,
++                                struct v4l2_mbus_config *cfg)
+ {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+-      int ret;
++      int ret = 0;
+       if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+               ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
+-      else
++      else if (cfg->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+               ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
+       if (ret)
+-              return ret;
++              goto error;
+       if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+               ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
+-      else
++      else if (cfg->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+               ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
+       if (ret)
+-              return ret;
++              goto error;
+       if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+               ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
+-      else
++      else if (cfg->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+               ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
++error:
++      /*
++       * Update the configuration to report what is actually applied to
++       * the hardware.
++       */
++      ov6650_get_mbus_config(sd, pad, cfg);
++
+       return ret;
+ }
+@@ -956,8 +978,6 @@ static const struct v4l2_subdev_video_op
+       .s_stream       = ov6650_s_stream,
+       .g_frame_interval = ov6650_g_frame_interval,
+       .s_frame_interval = ov6650_s_frame_interval,
+-      .g_mbus_config  = ov6650_g_mbus_config,
+-      .s_mbus_config  = ov6650_s_mbus_config,
+ };
+ static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
+@@ -966,6 +986,8 @@ static const struct v4l2_subdev_pad_ops
+       .set_selection  = ov6650_set_selection,
+       .get_fmt        = ov6650_get_fmt,
+       .set_fmt        = ov6650_set_fmt,
++      .get_mbus_config = ov6650_get_mbus_config,
++      .set_mbus_config = ov6650_set_mbus_config,
+ };
+ static const struct v4l2_subdev_ops ov6650_subdev_ops = {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch b/target/linux/bcm27xx/patches-5.4/950-0798-media-pxa_camera-Use-the-new-set_mbus_config-op.patch
new file mode 100644 (file)
index 0000000..d682cf8
--- /dev/null
@@ -0,0 +1,285 @@
+From 63f4970ce038e60455a6225b317d0b259e046c94 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:39 +0200
+Subject: [PATCH] media: pxa_camera: Use the new set_mbus_config op
+
+Upstream https://patchwork.linuxtv.org/patch/64671/
+
+Move the PXA camera driver to use the new set_mbus_config pad operation.
+For this platform the change is not only cosmetic, as the pxa driver is
+currently the only driver in mainline to make use of the g_mbus_config
+and s_mbus_config video operations.
+
+The existing driver semantic is the following:
+- Collect all supported mbus config flags from the remote end
+- Match them with the supported PXA mbus configuration flags
+- If the remote subdevice allows multiple options for for VSYNC, HSYNC
+  and PCLK polarity, use platform data requested settings
+
+The semantic of the new get_mbus_config and set_mbus_config differs from
+the corresponding video ops, particularly in the fact get_mbus_config
+reports the current mbus configuration and not the set of supported
+configuration options, with set_mbus_config always reporting the actual
+mbus configuration applied to the remote subdevice.
+
+Adapt the driver to perform the following
+- Set the remote subdevice mbus configuration according to the PXA
+  platform data preferences.
+- If the applied configuration differs from the requested one (i.e. the
+  remote subdevice does not allow changing one setting) make sure that
+  - The remote end does not claim for DATA_ACTIVE_LOW, which seems not
+    supported by the platform
+  - The bus mastering roles match
+
+While at there remove a few checks performed on the media bus
+configuration at get_format() time as they do not belong there.
+
+Compile-tested only.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/platform/pxa_camera.c | 189 ++++++++--------------------
+ 1 file changed, 51 insertions(+), 138 deletions(-)
+
+--- a/drivers/media/platform/pxa_camera.c
++++ b/drivers/media/platform/pxa_camera.c
+@@ -605,42 +605,6 @@ static const struct pxa_mbus_pixelfmt *p
+       return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
+ }
+-static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
+-                                      unsigned int flags)
+-{
+-      unsigned long common_flags;
+-      bool hsync = true, vsync = true, pclk, data, mode;
+-      bool mipi_lanes, mipi_clock;
+-
+-      common_flags = cfg->flags & flags;
+-
+-      switch (cfg->type) {
+-      case V4L2_MBUS_PARALLEL:
+-              hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+-                                      V4L2_MBUS_HSYNC_ACTIVE_LOW);
+-              vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+-                                      V4L2_MBUS_VSYNC_ACTIVE_LOW);
+-              /* fall through */
+-      case V4L2_MBUS_BT656:
+-              pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
+-                                     V4L2_MBUS_PCLK_SAMPLE_FALLING);
+-              data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
+-                                     V4L2_MBUS_DATA_ACTIVE_LOW);
+-              mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
+-              return (!hsync || !vsync || !pclk || !data || !mode) ?
+-                      0 : common_flags;
+-      case V4L2_MBUS_CSI2_DPHY:
+-              mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
+-              mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
+-                                           V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
+-              return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
+-      default:
+-              WARN_ON(1);
+-              return -EINVAL;
+-      }
+-      return 0;
+-}
+-
+ /**
+  * struct pxa_camera_format_xlate - match between host and sensor formats
+  * @code: code of a sensor provided format
+@@ -1231,31 +1195,6 @@ static irqreturn_t pxa_camera_irq(int ir
+       return IRQ_HANDLED;
+ }
+-static int test_platform_param(struct pxa_camera_dev *pcdev,
+-                             unsigned char buswidth, unsigned long *flags)
+-{
+-      /*
+-       * Platform specified synchronization and pixel clock polarities are
+-       * only a recommendation and are only used during probing. The PXA270
+-       * quick capture interface supports both.
+-       */
+-      *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
+-                V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) |
+-              V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+-              V4L2_MBUS_HSYNC_ACTIVE_LOW |
+-              V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+-              V4L2_MBUS_VSYNC_ACTIVE_LOW |
+-              V4L2_MBUS_DATA_ACTIVE_HIGH |
+-              V4L2_MBUS_PCLK_SAMPLE_RISING |
+-              V4L2_MBUS_PCLK_SAMPLE_FALLING;
+-
+-      /* If requested data width is supported by the platform, use it */
+-      if ((1 << (buswidth - 1)) & pcdev->width_flags)
+-              return 0;
+-
+-      return -EINVAL;
+-}
+-
+ static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev,
+                                 unsigned long flags, __u32 pixfmt)
+ {
+@@ -1598,99 +1537,78 @@ static int pxa_camera_init_videobuf2(str
+  */
+ static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev)
+ {
++      unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc;
+-      unsigned long bus_flags, common_flags;
++      int mbus_config;
+       int ret;
+-      ret = test_platform_param(pcdev,
+-                                pcdev->current_fmt->host_fmt->bits_per_sample,
+-                                &bus_flags);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = sensor_call(pcdev, video, g_mbus_config, &cfg);
+-      if (!ret) {
+-              common_flags = pxa_mbus_config_compatible(&cfg,
+-                                                        bus_flags);
+-              if (!common_flags) {
+-                      dev_warn(pcdev_to_dev(pcdev),
+-                               "Flags incompatible: camera 0x%x, host 0x%lx\n",
+-                               cfg.flags, bus_flags);
+-                      return -EINVAL;
+-              }
+-      } else if (ret != -ENOIOCTLCMD) {
+-              return ret;
+-      } else {
+-              common_flags = bus_flags;
++      if (!((1 << (bus_width - 1)) & pcdev->width_flags)) {
++              dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u",
++                      bus_width);
++              return -EINVAL;
+       }
+       pcdev->channels = 1;
+       /* Make choices, based on platform preferences */
+-      if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+-          (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
+-              if (pcdev->platform_flags & PXA_CAMERA_HSP)
+-                      common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
+-              else
+-                      common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
+-      }
+-
+-      if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+-          (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
+-              if (pcdev->platform_flags & PXA_CAMERA_VSP)
+-                      common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
+-              else
+-                      common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
+-      }
+-
+-      if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+-          (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
+-              if (pcdev->platform_flags & PXA_CAMERA_PCP)
+-                      common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
+-              else
+-                      common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
+-      }
+-
+-      cfg.flags = common_flags;
+-      ret = sensor_call(pcdev, video, s_mbus_config, &cfg);
+-      if (ret < 0 && ret != -ENOIOCTLCMD) {
+-              dev_dbg(pcdev_to_dev(pcdev),
+-                      "camera s_mbus_config(0x%lx) returned %d\n",
+-                      common_flags, ret);
+-              return ret;
+-      }
++      mbus_config = 0;
++      if (pcdev->platform_flags & PXA_CAMERA_MASTER)
++              mbus_config |= V4L2_MBUS_MASTER;
++      else
++              mbus_config |= V4L2_MBUS_SLAVE;
+-      pxa_camera_setup_cicr(pcdev, common_flags, pixfmt);
++      if (pcdev->platform_flags & PXA_CAMERA_HSP)
++              mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH;
++      else
++              mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW;
+-      return 0;
+-}
++      if (pcdev->platform_flags & PXA_CAMERA_VSP)
++              mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH;
++      else
++              mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW;
+-static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev,
+-                                  unsigned char buswidth)
+-{
+-      struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+-      unsigned long bus_flags, common_flags;
+-      int ret = test_platform_param(pcdev, buswidth, &bus_flags);
++      if (pcdev->platform_flags & PXA_CAMERA_PCP)
++              mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING;
++      else
++              mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING;
++      mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH;
+-      if (ret < 0)
++      cfg.flags = mbus_config;
++      ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg);
++      if (ret < 0 && ret != -ENOIOCTLCMD) {
++              dev_err(pcdev_to_dev(pcdev),
++                      "Failed to call set_mbus_config: %d\n", ret);
+               return ret;
++      }
++
++      /*
++       * If the requested media bus configuration has not been fully applied
++       * make sure it is supported by the platform.
++       *
++       * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering
++       * roles should match.
++       */
++      if (cfg.flags != mbus_config) {
++              unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER |
++                                                          V4L2_MBUS_SLAVE);
++              if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER |
++                                                 V4L2_MBUS_SLAVE))) {
++                      dev_err(pcdev_to_dev(pcdev),
++                              "Unsupported mbus configuration: bus mastering\n");
++                      return -EINVAL;
++              }
+-      ret = sensor_call(pcdev, video, g_mbus_config, &cfg);
+-      if (!ret) {
+-              common_flags = pxa_mbus_config_compatible(&cfg,
+-                                                        bus_flags);
+-              if (!common_flags) {
+-                      dev_warn(pcdev_to_dev(pcdev),
+-                               "Flags incompatible: camera 0x%x, host 0x%lx\n",
+-                               cfg.flags, bus_flags);
++              if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) {
++                      dev_err(pcdev_to_dev(pcdev),
++                              "Unsupported mbus configuration: DATA_ACTIVE_LOW\n");
+                       return -EINVAL;
+               }
+-      } else if (ret == -ENOIOCTLCMD) {
+-              ret = 0;
+       }
+-      return ret;
++      pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt);
++
++      return 0;
+ }
+ static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = {
+@@ -1738,11 +1656,6 @@ static int pxa_camera_get_formats(struct
+               return 0;
+       }
+-      /* This also checks support for the requested bits-per-sample */
+-      ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample);
+-      if (ret < 0)
+-              return 0;
+-
+       switch (code.code) {
+       case MEDIA_BUS_FMT_UYVY8_2X8:
+               formats++;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0799-media-v4l2-subdev-Remove-s-g-_mbus_config-video-ops.patch b/target/linux/bcm27xx/patches-5.4/950-0799-media-v4l2-subdev-Remove-s-g-_mbus_config-video-ops.patch
new file mode 100644 (file)
index 0000000..a7186da
--- /dev/null
@@ -0,0 +1,43 @@
+From 316ebebe8edf42f264a0b2225adc5baa46451415 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:40 +0200
+Subject: [PATCH]_mbus_config video
+ ops
+
+Upstream https://patchwork.linuxtv.org/patch/64670/
+
+With all sensor and platform drivers now converted to use the new
+get_mbus_config and set_mbus_config pad operations, remove the
+deprecated video operations g_mbus_config and s_mbus_config.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ include/media/v4l2-subdev.h | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -402,12 +402,6 @@ struct v4l2_mbus_frame_desc {
+  *
+  * @query_dv_timings: callback for VIDIOC_QUERY_DV_TIMINGS() ioctl handler code.
+  *
+- * @g_mbus_config: get supported mediabus configurations
+- *
+- * @s_mbus_config: set a certain mediabus configuration. This operation is added
+- *    for compatibility with soc-camera drivers and should not be used by new
+- *    software.
+- *
+  * @s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
+  *    can adjust @size to a lower value and must not write more data to the
+  *    buffer starting at @data than the original value of @size.
+@@ -435,10 +429,6 @@ struct v4l2_subdev_video_ops {
+                       struct v4l2_dv_timings *timings);
+       int (*query_dv_timings)(struct v4l2_subdev *sd,
+                       struct v4l2_dv_timings *timings);
+-      int (*g_mbus_config)(struct v4l2_subdev *sd,
+-                           struct v4l2_mbus_config *cfg);
+-      int (*s_mbus_config)(struct v4l2_subdev *sd,
+-                           const struct v4l2_mbus_config *cfg);
+       int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
+                          unsigned int *size);
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0800-staging-media-imx-Update-TODO-entry.patch b/target/linux/bcm27xx/patches-5.4/950-0800-staging-media-imx-Update-TODO-entry.patch
new file mode 100644 (file)
index 0000000..6d4b569
--- /dev/null
@@ -0,0 +1,28 @@
+From 3dff4096a98f9ebb3fbc1ed7275d2d64f299db26 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:41 +0200
+Subject: [PATCH] staging: media: imx: Update TODO entry
+
+Upstream https://patchwork.linuxtv.org/patch/64672/
+
+Update the TODO entry that mentioned a potential use case for the now
+removed g_mbus_config video operation.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/staging/media/imx/TODO | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/staging/media/imx/TODO
++++ b/drivers/staging/media/imx/TODO
+@@ -10,6 +10,10 @@
+   driver uses the parsed DT bus config method until this issue is
+   resolved.
++  2020-06: g_mbus has been removed in favour of the get_mbus_config pad
++  operation which should be used to avoid parsing the remote endpoint
++  configuration.
++
+ - This media driver supports inheriting V4L2 controls to the
+   video capture devices, from the subdevices in the capture device's
+   pipeline. The controls for each capture device are updated in the
diff --git a/target/linux/bcm27xx/patches-5.4/950-0801-media-i2c-adv748x-Adjust-TXA-data-lanes-number.patch b/target/linux/bcm27xx/patches-5.4/950-0801-media-i2c-adv748x-Adjust-TXA-data-lanes-number.patch
new file mode 100644 (file)
index 0000000..b4a9753
--- /dev/null
@@ -0,0 +1,123 @@
+From a3fddd6eaaa8740aceeeefea6548d5313412a062 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:42 +0200
+Subject: [PATCH] media: i2c: adv748x: Adjust TXA data lanes number
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Upstream https://patchwork.linuxtv.org/patch/64673/
+
+When outputting SD-Core output through the TXA MIPI CSI-2 interface,
+the number of enabled data lanes should be reduced in order to guarantee
+that the two video formats produced by the SD-Core (480i and 576i)
+generate a MIPI CSI-2 link clock frequency compatible with the MIPI D-PHY
+specifications.
+
+Limit the number of enabled data lanes to 2, which is guaranteed to
+support 480i and 576i formats.
+
+Cache the number of enabled data lanes to be able to report it through
+the new get_mbus_config operation.
+
+Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/i2c/adv748x/adv748x-core.c | 31 ++++++++++++++++++------
+ drivers/media/i2c/adv748x/adv748x.h      |  1 +
+ 2 files changed, 25 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/i2c/adv748x/adv748x-core.c
++++ b/drivers/media/i2c/adv748x/adv748x-core.c
+@@ -241,10 +241,10 @@ static int adv748x_power_up_tx(struct ad
+       int ret = 0;
+       /* Enable n-lane MIPI */
+-      adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret);
++      adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret);
+       /* Set Auto DPHY Timing */
+-      adv748x_write_check(state, page, 0x00, 0xa0 | tx->num_lanes, &ret);
++      adv748x_write_check(state, page, 0x00, 0xa0 | tx->active_lanes, &ret);
+       /* ADI Required Write */
+       if (tx->src == &state->hdmi.sd) {
+@@ -270,7 +270,7 @@ static int adv748x_power_up_tx(struct ad
+       usleep_range(2000, 2500);
+       /* Power-up CSI-TX */
+-      adv748x_write_check(state, page, 0x00, 0x20 | tx->num_lanes, &ret);
++      adv748x_write_check(state, page, 0x00, 0x20 | tx->active_lanes, &ret);
+       usleep_range(1000, 1500);
+       /* ADI Required Writes */
+@@ -292,7 +292,7 @@ static int adv748x_power_down_tx(struct
+       adv748x_write_check(state, page, 0x1e, 0x00, &ret);
+       /* Enable n-lane MIPI */
+-      adv748x_write_check(state, page, 0x00, 0x80 | tx->num_lanes, &ret);
++      adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret);
+       /* i2c_mipi_pll_en - 1'b1 */
+       adv748x_write_check(state, page, 0xda, 0x01, &ret);
+@@ -357,14 +357,29 @@ static int adv748x_link_setup(struct med
+       if (state->afe.tx) {
+               /* AFE Requires TXA enabled, even when output to TXB */
+               io10 |= ADV748X_IO_10_CSI4_EN;
+-              if (is_txa(tx))
++              if (is_txa(tx)) {
++                      /*
++                       * Output from the SD-core (480i and 576i) from the TXA
++                       * interface requires reducing the number of enabled
++                       * data lanes in order to guarantee a valid link
++                       * frequency.
++                       */
++                      tx->active_lanes = min(tx->num_lanes, 2U);
+                       io10 |= ADV748X_IO_10_CSI4_IN_SEL_AFE;
+-              else
++              } else {
++                      /* TXB has a single data lane, no need to adjust. */
+                       io10 |= ADV748X_IO_10_CSI1_EN;
++              }
+       }
+-      if (state->hdmi.tx)
++      if (state->hdmi.tx) {
++              /*
++               * Restore the number of active lanes, in case we have gone
++               * through an AFE->TXA streaming sessions.
++               */
++              tx->active_lanes = tx->num_lanes;
+               io10 |= ADV748X_IO_10_CSI4_EN;
++      }
+       return io_clrset(state, ADV748X_IO_10, io10_mask, io10);
+ }
+@@ -596,6 +611,7 @@ static int adv748x_parse_csi2_lanes(stru
+               }
+               state->txa.num_lanes = num_lanes;
++              state->txa.active_lanes = num_lanes;
+               adv_dbg(state, "TXA: using %u lanes\n", state->txa.num_lanes);
+       }
+@@ -607,6 +623,7 @@ static int adv748x_parse_csi2_lanes(stru
+               }
+               state->txb.num_lanes = num_lanes;
++              state->txb.active_lanes = num_lanes;
+               adv_dbg(state, "TXB: using %u lanes\n", state->txb.num_lanes);
+       }
+--- a/drivers/media/i2c/adv748x/adv748x.h
++++ b/drivers/media/i2c/adv748x/adv748x.h
+@@ -79,6 +79,7 @@ struct adv748x_csi2 {
+       unsigned int page;
+       unsigned int port;
+       unsigned int num_lanes;
++      unsigned int active_lanes;
+       struct media_pad pads[ADV748X_CSI2_NR_PADS];
+       struct v4l2_ctrl_handler ctrl_hdl;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0802-media-i2c-adv748x-Implement-get_mbus_config.patch b/target/linux/bcm27xx/patches-5.4/950-0802-media-i2c-adv748x-Implement-get_mbus_config.patch
new file mode 100644 (file)
index 0000000..19c4d4c
--- /dev/null
@@ -0,0 +1,63 @@
+From 3269627852346852f99244b2650daaa79056b29d Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:43 +0200
+Subject: [PATCH] media: i2c: adv748x: Implement get_mbus_config
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Upstream https://patchwork.linuxtv.org/patch/64676/
+
+Implement the newly introduced get_mbus_config operation to report the
+number of currently used data lanes on the MIPI CSI-2 interface.
+
+Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/i2c/adv748x/adv748x-csi2.c | 31 ++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
++++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
+@@ -214,9 +214,40 @@ unlock:
+       return ret;
+ }
++static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
++                                      struct v4l2_mbus_config *config)
++{
++      struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
++
++      if (pad != ADV748X_CSI2_SOURCE)
++              return -EINVAL;
++
++      config->type = V4L2_MBUS_CSI2_DPHY;
++      switch (tx->active_lanes) {
++      case 1:
++              config->flags = V4L2_MBUS_CSI2_1_LANE;
++              break;
++
++      case 2:
++              config->flags = V4L2_MBUS_CSI2_2_LANE;
++              break;
++
++      case 3:
++              config->flags = V4L2_MBUS_CSI2_3_LANE;
++              break;
++
++      case 4:
++              config->flags = V4L2_MBUS_CSI2_4_LANE;
++              break;
++      }
++
++      return 0;
++}
++
+ static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
+       .get_fmt = adv748x_csi2_get_format,
+       .set_fmt = adv748x_csi2_set_format,
++      .get_mbus_config = adv748x_csi2_get_mbus_config,
+ };
+ /* -----------------------------------------------------------------------------
diff --git a/target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch b/target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch
new file mode 100644 (file)
index 0000000..f54b33e
--- /dev/null
@@ -0,0 +1,159 @@
+From 15221304a23fd99c84a6da4b68dc0e887150d1ee Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:44 +0200
+Subject: [PATCH] media: rcar-csi2: Negotiate data lanes number
+
+Upstream https://patchwork.linuxtv.org/patch/64675/
+
+Use the newly introduced get_mbus_config() subdevice pad operation to
+retrieve the remote subdevice MIPI CSI-2 bus configuration and configure
+the number of active data lanes accordingly.
+
+In order to be able to call the remote subdevice operation cache the
+index of the remote pad connected to the single CSI-2 input port.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/platform/rcar-vin/rcar-csi2.c | 74 +++++++++++++++++++--
+ 1 file changed, 67 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
+@@ -362,6 +362,7 @@ struct rcar_csi2 {
+       struct v4l2_async_notifier notifier;
+       struct v4l2_subdev *remote;
++      unsigned int remote_pad;
+       struct v4l2_mbus_framefmt mf;
+@@ -407,13 +408,14 @@ static void rcsi2_exit_standby(struct rc
+       reset_control_deassert(priv->rstc);
+ }
+-static int rcsi2_wait_phy_start(struct rcar_csi2 *priv)
++static int rcsi2_wait_phy_start(struct rcar_csi2 *priv,
++                              unsigned int active_lanes)
+ {
+       unsigned int timeout;
+       /* Wait for the clock and data lanes to enter LP-11 state. */
+       for (timeout = 0; timeout <= 20; timeout++) {
+-              const u32 lane_mask = (1 << priv->lanes) - 1;
++              const u32 lane_mask = (1 << active_lanes) - 1;
+               if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL)  &&
+                   (rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask)
+@@ -445,7 +447,8 @@ static int rcsi2_set_phypll(struct rcar_
+       return 0;
+ }
+-static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
++static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp,
++                         unsigned int active_lanes)
+ {
+       struct v4l2_subdev *source;
+       struct v4l2_ctrl *ctrl;
+@@ -470,15 +473,63 @@ static int rcsi2_calc_mbps(struct rcar_c
+        * bps = link_freq * 2
+        */
+       mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp;
+-      do_div(mbps, priv->lanes * 1000000);
++      do_div(mbps, active_lanes * 1000000);
+       return mbps;
+ }
++static int rcsi2_config_active_lanes(struct rcar_csi2 *priv,
++                                   unsigned int *active_lanes)
++{
++      struct v4l2_mbus_config mbus_config = { 0 };
++      unsigned int num_lanes = (-1U);
++      int ret;
++
++      *active_lanes = priv->lanes;
++      ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config,
++                             priv->remote_pad, &mbus_config);
++      if (ret == -ENOIOCTLCMD) {
++              dev_dbg(priv->dev, "No remote mbus configuration available\n");
++              return 0;
++      }
++
++      if (ret) {
++              dev_err(priv->dev, "Failed to get remote mbus configuration\n");
++              return ret;
++      }
++
++      if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) {
++              dev_err(priv->dev, "Unsupported media bus type %u\n",
++                      mbus_config.type);
++              return -EINVAL;
++      }
++
++      if (mbus_config.flags & V4L2_MBUS_CSI2_1_LANE)
++              num_lanes = 1;
++      else if (mbus_config.flags & V4L2_MBUS_CSI2_2_LANE)
++              num_lanes = 2;
++      else if (mbus_config.flags & V4L2_MBUS_CSI2_3_LANE)
++              num_lanes = 3;
++      else if (mbus_config.flags & V4L2_MBUS_CSI2_4_LANE)
++              num_lanes = 4;
++
++      if (num_lanes > priv->lanes) {
++              dev_err(priv->dev,
++                      "Unsupported mbus config: too many data lanes %u\n",
++                      num_lanes);
++              return -EINVAL;
++      }
++
++      *active_lanes = num_lanes;
++
++      return 0;
++}
++
+ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
+ {
+       const struct rcar_csi2_format *format;
+       u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
++      unsigned int active_lanes;
+       unsigned int i;
+       int mbps, ret;
+@@ -520,10 +571,18 @@ static int rcsi2_start_receiver(struct r
+                       fld |= FLD_FLD_NUM(1);
+       }
++      /*
++       * Get the number of active data lanes inspecting the remote mbus
++       * configuration.
++       */
++      ret = rcsi2_config_active_lanes(priv, &active_lanes);
++      if (ret)
++              return ret;
++
+       phycnt = PHYCNT_ENABLECLK;
+-      phycnt |= (1 << priv->lanes) - 1;
++      phycnt |= (1 << active_lanes) - 1;
+-      mbps = rcsi2_calc_mbps(priv, format->bpp);
++      mbps = rcsi2_calc_mbps(priv, format->bpp, active_lanes);
+       if (mbps < 0)
+               return mbps;
+@@ -570,7 +629,7 @@ static int rcsi2_start_receiver(struct r
+       rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);
+       rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);
+-      ret = rcsi2_wait_phy_start(priv);
++      ret = rcsi2_wait_phy_start(priv, active_lanes);
+       if (ret)
+               return ret;
+@@ -747,6 +806,7 @@ static int rcsi2_notify_bound(struct v4l
+       }
+       priv->remote = subdev;
++      priv->remote_pad = pad;
+       dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0804-drivers-media-Remove-the-downstream-version-of-bcm28.patch b/target/linux/bcm27xx/patches-5.4/950-0804-drivers-media-Remove-the-downstream-version-of-bcm28.patch
new file mode 100644 (file)
index 0000000..f4a89a9
--- /dev/null
@@ -0,0 +1,3175 @@
+From c6a423459a233669b280e1a4e4836881d77c9ff0 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 23 Jun 2020 10:05:57 +0100
+Subject: [PATCH] drivers: media: Remove the downstream version of
+ bcm2835-unicam
+
+About to be replaced by the upstream version.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/Kconfig        |   14 -
+ drivers/media/platform/bcm2835/Makefile       |    3 -
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 2873 -----------------
+ .../media/platform/bcm2835/vc4-regs-unicam.h  |  253 --
+ 4 files changed, 3143 deletions(-)
+ delete mode 100644 drivers/media/platform/bcm2835/Kconfig
+ delete mode 100644 drivers/media/platform/bcm2835/Makefile
+ delete mode 100644 drivers/media/platform/bcm2835/bcm2835-unicam.c
+ delete mode 100644 drivers/media/platform/bcm2835/vc4-regs-unicam.h
+
+--- a/drivers/media/platform/bcm2835/Kconfig
++++ /dev/null
+@@ -1,14 +0,0 @@
+-# Broadcom VideoCore4 V4L2 camera support
+-
+-config VIDEO_BCM2835_UNICAM
+-      tristate "Broadcom BCM2835 Unicam video capture driver"
+-      depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+-      depends on ARCH_BCM2835 || COMPILE_TEST
+-      select VIDEOBUF2_DMA_CONTIG
+-      select V4L2_FWNODE
+-      help
+-        Say Y here to enable V4L2 subdevice for CSI2 receiver.
+-        This is a V4L2 subdevice that interfaces directly to the VC4 peripheral.
+-
+-         To compile this driver as a module, choose M here. The module
+-         will be called bcm2835-unicam.
+--- a/drivers/media/platform/bcm2835/Makefile
++++ /dev/null
+@@ -1,3 +0,0 @@
+-# Makefile for BCM2835 Unicam driver
+-
+-obj-$(CONFIG_VIDEO_BCM2835_UNICAM) += bcm2835-unicam.o
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ /dev/null
+@@ -1,2873 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- * BCM2835 Unicam Capture Driver
+- *
+- * Copyright (C) 2017-2020 - Raspberry Pi (Trading) Ltd.
+- *
+- * Dave Stevenson <dave.stevenson@raspberrypi.com>
+- *
+- * Based on TI am437x driver by
+- *   Benoit Parrot <bparrot@ti.com>
+- *   Lad, Prabhakar <prabhakar.csengg@gmail.com>
+- *
+- * and TI CAL camera interface driver by
+- *    Benoit Parrot <bparrot@ti.com>
+- *
+- *
+- * There are two camera drivers in the kernel for BCM283x - this one
+- * and bcm2835-camera (currently in staging).
+- *
+- * This driver directly controls the Unicam peripheral - there is no
+- * involvement with the VideoCore firmware. Unicam receives CSI-2 or
+- * CCP2 data and writes it into SDRAM.
+- * The only potential processing options are to repack Bayer data into an
+- * alternate format, and applying windowing.
+- * The repacking does not shift the data, so can repack V4L2_PIX_FMT_Sxxxx10P
+- * to V4L2_PIX_FMT_Sxxxx10, or V4L2_PIX_FMT_Sxxxx12P to V4L2_PIX_FMT_Sxxxx12,
+- * but not generically up to V4L2_PIX_FMT_Sxxxx16. The driver will add both
+- * formats where the relevant formats are defined, and will automatically
+- * configure the repacking as required.
+- * Support for windowing may be added later.
+- *
+- * It should be possible to connect this driver to any sensor with a
+- * suitable output interface and V4L2 subdevice driver.
+- *
+- * bcm2835-camera uses the VideoCore firmware to control the sensor,
+- * Unicam, ISP, and all tuner control loops. Fully processed frames are
+- * delivered to the driver by the firmware. It only has sensor drivers
+- * for Omnivision OV5647, and Sony IMX219 sensors.
+- *
+- * The two drivers are mutually exclusive for the same Unicam instance.
+- * The VideoCore firmware checks the device tree configuration during boot.
+- * If it finds device tree nodes called csi0 or csi1 it will block the
+- * firmware from accessing the peripheral, and bcm2835-camera will
+- * not be able to stream data.
+- */
+-
+-#include <linux/clk.h>
+-#include <linux/delay.h>
+-#include <linux/device.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/io.h>
+-#include <linux/module.h>
+-#include <linux/of_device.h>
+-#include <linux/of_graph.h>
+-#include <linux/pinctrl/consumer.h>
+-#include <linux/platform_device.h>
+-#include <linux/pm_runtime.h>
+-#include <linux/slab.h>
+-#include <linux/uaccess.h>
+-#include <linux/videodev2.h>
+-
+-#include <media/v4l2-common.h>
+-#include <media/v4l2-ctrls.h>
+-#include <media/v4l2-dev.h>
+-#include <media/v4l2-device.h>
+-#include <media/v4l2-dv-timings.h>
+-#include <media/v4l2-event.h>
+-#include <media/v4l2-ioctl.h>
+-#include <media/v4l2-fwnode.h>
+-#include <media/videobuf2-dma-contig.h>
+-
+-#include "vc4-regs-unicam.h"
+-
+-#define UNICAM_MODULE_NAME    "unicam"
+-#define UNICAM_VERSION                "0.1.0"
+-
+-static int debug;
+-module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug, "Debug level 0-3");
+-
+-#define unicam_dbg(level, dev, fmt, arg...)   \
+-              v4l2_dbg(level, debug, &(dev)->v4l2_dev, fmt, ##arg)
+-#define unicam_info(dev, fmt, arg...) \
+-              v4l2_info(&(dev)->v4l2_dev, fmt, ##arg)
+-#define unicam_err(dev, fmt, arg...)  \
+-              v4l2_err(&(dev)->v4l2_dev, fmt, ##arg)
+-
+-/* To protect against a dodgy sensor driver never returning an error from
+- * enum_mbus_code, set a maximum index value to be used.
+- */
+-#define MAX_ENUM_MBUS_CODE    128
+-
+-/*
+- * Stride is a 16 bit register, but also has to be a multiple of 32.
+- */
+-#define BPL_ALIGNMENT         32
+-#define MAX_BYTESPERLINE      ((1 << 16) - BPL_ALIGNMENT)
+-/*
+- * Max width is therefore determined by the max stride divided by
+- * the number of bits per pixel. Take 32bpp as a
+- * worst case.
+- * No imposed limit on the height, so adopt a square image for want
+- * of anything better.
+- */
+-#define MAX_WIDTH     (MAX_BYTESPERLINE / 4)
+-#define MAX_HEIGHT    MAX_WIDTH
+-/* Define a nominal minimum image size */
+-#define MIN_WIDTH     16
+-#define MIN_HEIGHT    16
+-/* Default size of the embedded buffer */
+-#define UNICAM_EMBEDDED_SIZE  8192
+-
+-/*
+- * Size of the dummy buffer. Can be any size really, but the DMA
+- * allocation works in units of page sizes.
+- */
+-#define DUMMY_BUF_SIZE        (PAGE_SIZE)
+-
+-enum pad_types {
+-      IMAGE_PAD,
+-      METADATA_PAD,
+-      MAX_NODES
+-};
+-
+-/*
+- * struct unicam_fmt - Unicam media bus format information
+- * @pixelformat: V4L2 pixel format FCC identifier. 0 if n/a.
+- * @repacked_fourcc: V4L2 pixel format FCC identifier if the data is expanded
+- * out to 16bpp. 0 if n/a.
+- * @code: V4L2 media bus format code.
+- * @depth: Bits per pixel as delivered from the source.
+- * @csi_dt: CSI data type.
+- * @check_variants: Flag to denote that there are multiple mediabus formats
+- *            still in the list that could match this V4L2 format.
+- */
+-struct unicam_fmt {
+-      u32     fourcc;
+-      u32     repacked_fourcc;
+-      u32     code;
+-      u8      depth;
+-      u8      csi_dt;
+-      u8      check_variants;
+-};
+-
+-static const struct unicam_fmt formats[] = {
+-      /* YUV Formats */
+-      {
+-              .fourcc         = V4L2_PIX_FMT_YUYV,
+-              .code           = MEDIA_BUS_FMT_YUYV8_2X8,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-              .check_variants = 1,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_UYVY,
+-              .code           = MEDIA_BUS_FMT_UYVY8_2X8,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-              .check_variants = 1,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_YVYU,
+-              .code           = MEDIA_BUS_FMT_YVYU8_2X8,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-              .check_variants = 1,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_VYUY,
+-              .code           = MEDIA_BUS_FMT_VYUY8_2X8,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-              .check_variants = 1,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_YUYV,
+-              .code           = MEDIA_BUS_FMT_YUYV8_1X16,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_UYVY,
+-              .code           = MEDIA_BUS_FMT_UYVY8_1X16,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_YVYU,
+-              .code           = MEDIA_BUS_FMT_YVYU8_1X16,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_VYUY,
+-              .code           = MEDIA_BUS_FMT_VYUY8_1X16,
+-              .depth          = 16,
+-              .csi_dt         = 0x1e,
+-      }, {
+-      /* RGB Formats */
+-              .fourcc         = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+-              .code           = MEDIA_BUS_FMT_RGB565_2X8_LE,
+-              .depth          = 16,
+-              .csi_dt         = 0x22,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+-              .code           = MEDIA_BUS_FMT_RGB565_2X8_BE,
+-              .depth          = 16,
+-              .csi_dt         = 0x22
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+-              .code           = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+-              .depth          = 16,
+-              .csi_dt         = 0x21,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+-              .code           = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+-              .depth          = 16,
+-              .csi_dt         = 0x21,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_RGB24, /* rgb */
+-              .code           = MEDIA_BUS_FMT_RGB888_1X24,
+-              .depth          = 24,
+-              .csi_dt         = 0x24,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_BGR24, /* bgr */
+-              .code           = MEDIA_BUS_FMT_BGR888_1X24,
+-              .depth          = 24,
+-              .csi_dt         = 0x24,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_RGB32, /* argb */
+-              .code           = MEDIA_BUS_FMT_ARGB8888_1X32,
+-              .depth          = 32,
+-              .csi_dt         = 0x0,
+-      }, {
+-      /* Bayer Formats */
+-              .fourcc         = V4L2_PIX_FMT_SBGGR8,
+-              .code           = MEDIA_BUS_FMT_SBGGR8_1X8,
+-              .depth          = 8,
+-              .csi_dt         = 0x2a,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGBRG8,
+-              .code           = MEDIA_BUS_FMT_SGBRG8_1X8,
+-              .depth          = 8,
+-              .csi_dt         = 0x2a,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGRBG8,
+-              .code           = MEDIA_BUS_FMT_SGRBG8_1X8,
+-              .depth          = 8,
+-              .csi_dt         = 0x2a,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SRGGB8,
+-              .code           = MEDIA_BUS_FMT_SRGGB8_1X8,
+-              .depth          = 8,
+-              .csi_dt         = 0x2a,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SBGGR10P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SBGGR10,
+-              .code           = MEDIA_BUS_FMT_SBGGR10_1X10,
+-              .depth          = 10,
+-              .csi_dt         = 0x2b,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGBRG10P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SGBRG10,
+-              .code           = MEDIA_BUS_FMT_SGBRG10_1X10,
+-              .depth          = 10,
+-              .csi_dt         = 0x2b,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGRBG10P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SGRBG10,
+-              .code           = MEDIA_BUS_FMT_SGRBG10_1X10,
+-              .depth          = 10,
+-              .csi_dt         = 0x2b,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SRGGB10P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SRGGB10,
+-              .code           = MEDIA_BUS_FMT_SRGGB10_1X10,
+-              .depth          = 10,
+-              .csi_dt         = 0x2b,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SBGGR12P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SBGGR12,
+-              .code           = MEDIA_BUS_FMT_SBGGR12_1X12,
+-              .depth          = 12,
+-              .csi_dt         = 0x2c,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGBRG12P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SGBRG12,
+-              .code           = MEDIA_BUS_FMT_SGBRG12_1X12,
+-              .depth          = 12,
+-              .csi_dt         = 0x2c,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGRBG12P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SGRBG12,
+-              .code           = MEDIA_BUS_FMT_SGRBG12_1X12,
+-              .depth          = 12,
+-              .csi_dt         = 0x2c,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SRGGB12P,
+-              .repacked_fourcc = V4L2_PIX_FMT_SRGGB12,
+-              .code           = MEDIA_BUS_FMT_SRGGB12_1X12,
+-              .depth          = 12,
+-              .csi_dt         = 0x2c,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SBGGR14P,
+-              .code           = MEDIA_BUS_FMT_SBGGR14_1X14,
+-              .depth          = 14,
+-              .csi_dt         = 0x2d,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGBRG14P,
+-              .code           = MEDIA_BUS_FMT_SGBRG14_1X14,
+-              .depth          = 14,
+-              .csi_dt         = 0x2d,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SGRBG14P,
+-              .code           = MEDIA_BUS_FMT_SGRBG14_1X14,
+-              .depth          = 14,
+-              .csi_dt         = 0x2d,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_SRGGB14P,
+-              .code           = MEDIA_BUS_FMT_SRGGB14_1X14,
+-              .depth          = 14,
+-              .csi_dt         = 0x2d,
+-      }, {
+-      /*
+-       * 16 bit Bayer formats could be supported, but there is no CSI2
+-       * data_type defined for raw 16, and no sensors that produce it at
+-       * present.
+-       */
+-
+-      /* Greyscale formats */
+-              .fourcc         = V4L2_PIX_FMT_GREY,
+-              .code           = MEDIA_BUS_FMT_Y8_1X8,
+-              .depth          = 8,
+-              .csi_dt         = 0x2a,
+-      }, {
+-              .fourcc         = V4L2_PIX_FMT_Y10P,
+-              .repacked_fourcc = V4L2_PIX_FMT_Y10,
+-              .code           = MEDIA_BUS_FMT_Y10_1X10,
+-              .depth          = 10,
+-              .csi_dt         = 0x2b,
+-      }, {
+-              /* NB There is no packed V4L2 fourcc for this format. */
+-              .repacked_fourcc = V4L2_PIX_FMT_Y12,
+-              .code           = MEDIA_BUS_FMT_Y12_1X12,
+-              .depth          = 12,
+-              .csi_dt         = 0x2c,
+-      },
+-      /* Embedded data format */
+-      {
+-              .fourcc         = V4L2_META_FMT_SENSOR_DATA,
+-              .code           = MEDIA_BUS_FMT_SENSOR_DATA,
+-              .depth          = 8,
+-      }
+-};
+-
+-struct unicam_dmaqueue {
+-      struct list_head        active;
+-};
+-
+-struct unicam_buffer {
+-      struct vb2_v4l2_buffer vb;
+-      struct list_head list;
+-};
+-
+-struct unicam_cfg {
+-      /* peripheral base address */
+-      void __iomem *base;
+-      /* clock gating base address */
+-      void __iomem *clk_gate_base;
+-};
+-
+-#define MAX_POSSIBLE_PIX_FMTS (ARRAY_SIZE(formats))
+-
+-struct unicam_node {
+-      int registered;
+-      int open;
+-      int streaming;
+-      unsigned int pad_id;
+-      /* Pointer pointing to current v4l2_buffer */
+-      struct unicam_buffer *cur_frm;
+-      /* Pointer pointing to next v4l2_buffer */
+-      struct unicam_buffer *next_frm;
+-      /* video capture */
+-      const struct unicam_fmt *fmt;
+-      /* Used to store current pixel format */
+-      struct v4l2_format v_fmt;
+-      /* Used to store current mbus frame format */
+-      struct v4l2_mbus_framefmt m_fmt;
+-      /* Buffer queue used in video-buf */
+-      struct vb2_queue buffer_queue;
+-      /* Queue of filled frames */
+-      struct unicam_dmaqueue dma_queue;
+-      /* IRQ lock for DMA queue */
+-      spinlock_t dma_queue_lock;
+-      /* lock used to access this structure */
+-      struct mutex lock;
+-      /* Identifies video device for this channel */
+-      struct video_device video_dev;
+-      /* Pointer to the parent handle */
+-      struct unicam_device *dev;
+-      struct media_pad pad;
+-      struct v4l2_ctrl_handler ctrl_handler;
+-      unsigned int embedded_lines;
+-      /*
+-       * Dummy buffer intended to be used by unicam
+-       * if we have no other queued buffers to swap to.
+-       */
+-      void *dummy_buf_cpu_addr;
+-      dma_addr_t dummy_buf_dma_addr;
+-};
+-
+-struct unicam_device {
+-      /* V4l2 specific parameters */
+-
+-      struct v4l2_fwnode_endpoint endpoint;
+-
+-      struct v4l2_async_subdev asd;
+-
+-      /* unicam cfg */
+-      struct unicam_cfg cfg;
+-      /* clock handle */
+-      struct clk *clock;
+-      /* V4l2 device */
+-      struct v4l2_device v4l2_dev;
+-      struct media_device mdev;
+-
+-      /* parent device */
+-      struct platform_device *pdev;
+-      /* subdevice async Notifier */
+-      struct v4l2_async_notifier notifier;
+-      unsigned int sequence;
+-
+-      /* ptr to  sub device */
+-      struct v4l2_subdev *sensor;
+-      /* Pad config for the sensor */
+-      struct v4l2_subdev_pad_config *sensor_config;
+-
+-      unsigned int virtual_channel;
+-      enum v4l2_mbus_type bus_type;
+-      /*
+-       * Stores bus.mipi_csi2.flags for CSI2 sensors, or
+-       * bus.mipi_csi1.strobe for CCP2.
+-       */
+-      unsigned int bus_flags;
+-      unsigned int max_data_lanes;
+-      unsigned int active_data_lanes;
+-      bool sensor_embedded_data;
+-
+-      struct unicam_node node[MAX_NODES];
+-};
+-
+-/* Hardware access */
+-#define clk_write(dev, val) writel((val) | 0x5a000000, (dev)->clk_gate_base)
+-#define clk_read(dev) readl((dev)->clk_gate_base)
+-
+-#define reg_read(dev, offset) readl((dev)->base + (offset))
+-#define reg_write(dev, offset, val) writel(val, (dev)->base + (offset))
+-
+-#define reg_read_field(dev, offset, mask) get_field(reg_read((dev), (offset), \
+-                                                  mask))
+-
+-static inline int get_field(u32 value, u32 mask)
+-{
+-      return (value & mask) >> __ffs(mask);
+-}
+-
+-static inline void set_field(u32 *valp, u32 field, u32 mask)
+-{
+-      u32 val = *valp;
+-
+-      val &= ~mask;
+-      val |= (field << __ffs(mask)) & mask;
+-      *valp = val;
+-}
+-
+-static inline void reg_write_field(struct unicam_cfg *dev, u32 offset,
+-                                 u32 field, u32 mask)
+-{
+-      u32 val = reg_read((dev), (offset));
+-
+-      set_field(&val, field, mask);
+-      reg_write((dev), (offset), val);
+-}
+-
+-/* Power management functions */
+-static inline int unicam_runtime_get(struct unicam_device *dev)
+-{
+-      return pm_runtime_get_sync(&dev->pdev->dev);
+-}
+-
+-static inline void unicam_runtime_put(struct unicam_device *dev)
+-{
+-      pm_runtime_put_sync(&dev->pdev->dev);
+-}
+-
+-/* Format setup functions */
+-static const struct unicam_fmt *find_format_by_code(u32 code)
+-{
+-      unsigned int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(formats); i++) {
+-              if (formats[i].code == code)
+-                      return &formats[i];
+-      }
+-
+-      return NULL;
+-}
+-
+-static int check_mbus_format(struct unicam_device *dev,
+-                           const struct unicam_fmt *format)
+-{
+-      struct v4l2_subdev_mbus_code_enum mbus_code;
+-      int ret = 0;
+-      int i;
+-
+-      for (i = 0; !ret && i < MAX_ENUM_MBUS_CODE; i++) {
+-              memset(&mbus_code, 0, sizeof(mbus_code));
+-              mbus_code.index = i;
+-              mbus_code.pad = IMAGE_PAD;
+-              mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+-
+-              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code,
+-                                     NULL, &mbus_code);
+-
+-              if (!ret && mbus_code.code == format->code)
+-                      return 1;
+-      }
+-
+-      return 0;
+-}
+-
+-static const struct unicam_fmt *find_format_by_pix(struct unicam_device *dev,
+-                                                 u32 pixelformat)
+-{
+-      unsigned int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(formats); i++) {
+-              if (formats[i].fourcc == pixelformat ||
+-                  formats[i].repacked_fourcc == pixelformat) {
+-                      if (formats[i].check_variants &&
+-                          !check_mbus_format(dev, &formats[i]))
+-                              continue;
+-                      return &formats[i];
+-              }
+-      }
+-
+-      return NULL;
+-}
+-
+-static inline unsigned int bytes_per_line(u32 width,
+-                                        const struct unicam_fmt *fmt,
+-                                        u32 v4l2_fourcc)
+-{
+-      if (v4l2_fourcc == fmt->repacked_fourcc)
+-              /* Repacking always goes to 16bpp */
+-              return ALIGN(width << 1, BPL_ALIGNMENT);
+-      else
+-              return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
+-}
+-
+-static int __subdev_get_format(struct unicam_device *dev,
+-                             struct v4l2_mbus_framefmt *fmt, int pad_id)
+-{
+-      struct v4l2_subdev_format sd_fmt = {
+-              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+-              .pad = pad_id
+-      };
+-      int ret;
+-
+-      ret = v4l2_subdev_call(dev->sensor, pad, get_fmt, dev->sensor_config,
+-                             &sd_fmt);
+-      if (ret < 0)
+-              return ret;
+-
+-      *fmt = sd_fmt.format;
+-
+-      unicam_dbg(1, dev, "%s %dx%d code:%04x\n", __func__,
+-                 fmt->width, fmt->height, fmt->code);
+-
+-      return 0;
+-}
+-
+-static int __subdev_set_format(struct unicam_device *dev,
+-                             struct v4l2_mbus_framefmt *fmt, int pad_id)
+-{
+-      struct v4l2_subdev_format sd_fmt = {
+-              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+-              .pad = pad_id
+-      };
+-      int ret;
+-
+-      sd_fmt.format = *fmt;
+-
+-      ret = v4l2_subdev_call(dev->sensor, pad, set_fmt, dev->sensor_config,
+-                             &sd_fmt);
+-      if (ret < 0)
+-              return ret;
+-
+-      if (pad_id == IMAGE_PAD)
+-              unicam_dbg(1, dev, "%s %dx%d code:%04x\n", __func__, fmt->width,
+-                         fmt->height, fmt->code);
+-      else
+-              unicam_dbg(1, dev, "%s Embedded data code:%04x\n", __func__,
+-                         sd_fmt.format.code);
+-
+-      return 0;
+-}
+-
+-static int unicam_calc_format_size_bpl(struct unicam_device *dev,
+-                                     const struct unicam_fmt *fmt,
+-                                     struct v4l2_format *f)
+-{
+-      unsigned int min_bytesperline;
+-
+-      v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 2,
+-                            &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0,
+-                            0);
+-
+-      min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt,
+-                                        f->fmt.pix.pixelformat);
+-
+-      if (f->fmt.pix.bytesperline > min_bytesperline &&
+-          f->fmt.pix.bytesperline <= MAX_BYTESPERLINE)
+-              f->fmt.pix.bytesperline = ALIGN(f->fmt.pix.bytesperline,
+-                                              BPL_ALIGNMENT);
+-      else
+-              f->fmt.pix.bytesperline = min_bytesperline;
+-
+-      f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+-
+-      unicam_dbg(3, dev, "%s: fourcc: %08X size: %dx%d bpl:%d img_size:%d\n",
+-                 __func__,
+-                 f->fmt.pix.pixelformat,
+-                 f->fmt.pix.width, f->fmt.pix.height,
+-                 f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
+-
+-      return 0;
+-}
+-
+-static int unicam_reset_format(struct unicam_node *node)
+-{
+-      struct unicam_device *dev = node->dev;
+-      struct v4l2_mbus_framefmt mbus_fmt;
+-      int ret;
+-
+-      if (dev->sensor_embedded_data || node->pad_id != METADATA_PAD) {
+-              ret = __subdev_get_format(dev, &mbus_fmt, node->pad_id);
+-              if (ret) {
+-                      unicam_err(dev, "Failed to get_format - ret %d\n", ret);
+-                      return ret;
+-              }
+-
+-              if (mbus_fmt.code != node->fmt->code) {
+-                      unicam_err(dev, "code mismatch - fmt->code %08x, mbus_fmt.code %08x\n",
+-                                 node->fmt->code, mbus_fmt.code);
+-                      return ret;
+-              }
+-      }
+-
+-      if (node->pad_id == IMAGE_PAD) {
+-              v4l2_fill_pix_format(&node->v_fmt.fmt.pix, &mbus_fmt);
+-              node->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-              unicam_calc_format_size_bpl(dev, node->fmt, &node->v_fmt);
+-      } else {
+-              node->v_fmt.type = V4L2_BUF_TYPE_META_CAPTURE;
+-              node->v_fmt.fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA;
+-              if (dev->sensor_embedded_data) {
+-                      node->v_fmt.fmt.meta.buffersize =
+-                                      mbus_fmt.width * mbus_fmt.height;
+-                      node->embedded_lines = mbus_fmt.height;
+-              } else {
+-                      node->v_fmt.fmt.meta.buffersize = UNICAM_EMBEDDED_SIZE;
+-                      node->embedded_lines = 1;
+-              }
+-      }
+-
+-      node->m_fmt = mbus_fmt;
+-      return 0;
+-}
+-
+-static void unicam_wr_dma_addr(struct unicam_cfg *cfg, dma_addr_t dmaaddr,
+-                             unsigned int buffer_size, int pad_id)
+-{
+-      dma_addr_t endaddr = dmaaddr + buffer_size;
+-
+-      /*
+-       * dmaaddr and endaddr should be a 32-bit address with the top two bits
+-       * set to 0x3 to signify uncached access through the Videocore memory
+-       * controller.
+-       */
+-      BUG_ON((dmaaddr >> 30) != 0x3 && (endaddr >> 30) != 0x3);
+-
+-      if (pad_id == IMAGE_PAD) {
+-              reg_write(cfg, UNICAM_IBSA0, dmaaddr);
+-              reg_write(cfg, UNICAM_IBEA0, endaddr);
+-      } else {
+-              reg_write(cfg, UNICAM_DBSA0, dmaaddr);
+-              reg_write(cfg, UNICAM_DBEA0, endaddr);
+-      }
+-}
+-
+-static inline unsigned int unicam_get_lines_done(struct unicam_device *dev)
+-{
+-      dma_addr_t start_addr, cur_addr;
+-      unsigned int stride = dev->node[IMAGE_PAD].v_fmt.fmt.pix.bytesperline;
+-      struct unicam_buffer *frm = dev->node[IMAGE_PAD].cur_frm;
+-
+-      if (!frm)
+-              return 0;
+-
+-      start_addr = vb2_dma_contig_plane_dma_addr(&frm->vb.vb2_buf, 0);
+-      cur_addr = reg_read(&dev->cfg, UNICAM_IBWP);
+-      return (unsigned int)(cur_addr - start_addr) / stride;
+-}
+-
+-static inline void unicam_schedule_next_buffer(struct unicam_node *node)
+-{
+-      struct unicam_device *dev = node->dev;
+-      struct unicam_dmaqueue *dma_q = &node->dma_queue;
+-      struct unicam_buffer *buf;
+-      unsigned int size;
+-      dma_addr_t addr;
+-
+-      buf = list_entry(dma_q->active.next, struct unicam_buffer, list);
+-      node->next_frm = buf;
+-      list_del(&buf->list);
+-
+-      addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+-      size = (node->pad_id == IMAGE_PAD) ?
+-                      dev->node[IMAGE_PAD].v_fmt.fmt.pix.sizeimage :
+-                      dev->node[METADATA_PAD].v_fmt.fmt.meta.buffersize;
+-
+-      unicam_wr_dma_addr(&dev->cfg, addr, size, node->pad_id);
+-}
+-
+-static inline void unicam_schedule_dummy_buffer(struct unicam_node *node)
+-{
+-      struct unicam_device *dev = node->dev;
+-      dma_addr_t addr = node->dummy_buf_dma_addr;
+-
+-      unicam_dbg(3, dev, "Scheduling dummy buffer for node %d\n",
+-                 node->pad_id);
+-
+-      unicam_wr_dma_addr(&dev->cfg, addr, DUMMY_BUF_SIZE, node->pad_id);
+-      node->next_frm = NULL;
+-}
+-
+-static inline void unicam_process_buffer_complete(struct unicam_node *node,
+-                                                unsigned int sequence)
+-{
+-      node->cur_frm->vb.field = node->m_fmt.field;
+-      node->cur_frm->vb.sequence = sequence;
+-
+-      vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
+-}
+-
+-static int unicam_num_nodes_streaming(struct unicam_device *dev)
+-{
+-      return dev->node[IMAGE_PAD].streaming +
+-             dev->node[METADATA_PAD].streaming;
+-}
+-
+-static int unicam_all_nodes_streaming(struct unicam_device *dev)
+-{
+-      int ret;
+-
+-      ret = dev->node[IMAGE_PAD].open && dev->node[IMAGE_PAD].streaming;
+-      ret &= !dev->node[METADATA_PAD].open ||
+-             dev->node[METADATA_PAD].streaming;
+-      return ret;
+-}
+-
+-static void unicam_queue_event_sof(struct unicam_device *unicam)
+-{
+-      struct v4l2_event event = {
+-              .type = V4L2_EVENT_FRAME_SYNC,
+-              .u.frame_sync.frame_sequence = unicam->sequence,
+-      };
+-
+-      v4l2_event_queue(&unicam->node[IMAGE_PAD].video_dev, &event);
+-}
+-
+-/*
+- * unicam_isr : ISR handler for unicam capture
+- * @irq: irq number
+- * @dev_id: dev_id ptr
+- *
+- * It changes status of the captured buffer, takes next buffer from the queue
+- * and sets its address in unicam registers
+- */
+-static irqreturn_t unicam_isr(int irq, void *dev)
+-{
+-      struct unicam_device *unicam = (struct unicam_device *)dev;
+-      struct unicam_cfg *cfg = &unicam->cfg;
+-      unsigned int lines_done = unicam_get_lines_done(dev);
+-      unsigned int sequence = unicam->sequence;
+-      int num_nodes_streaming = unicam_num_nodes_streaming(dev);
+-      int ista, sta;
+-      u64 ts;
+-      int i;
+-
+-      sta = reg_read(cfg, UNICAM_STA);
+-      /* Write value back to clear the interrupts */
+-      reg_write(cfg, UNICAM_STA, sta);
+-
+-      ista = reg_read(cfg, UNICAM_ISTA);
+-      /* Write value back to clear the interrupts */
+-      reg_write(cfg, UNICAM_ISTA, ista);
+-
+-      unicam_dbg(3, unicam, "ISR: ISTA: 0x%X, STA: 0x%X, sequence %d, lines done %d",
+-                 ista, sta, sequence, lines_done);
+-
+-      if (!(sta && (UNICAM_IS | UNICAM_PI0)))
+-              return IRQ_HANDLED;
+-
+-      /*
+-       * We must run the frame end handler first. If we have a valid next_frm
+-       * and we get a simultaneout FE + FS interrupt, running the FS handler
+-       * first would null out the next_frm ptr and we would have lost the
+-       * buffer forever.
+-       */
+-      if (ista & UNICAM_FEI || sta & UNICAM_PI0) {
+-              /*
+-               * Ensure we have swapped buffers already as we can't
+-               * stop the peripheral. If no buffer is available, use a
+-               * dummy buffer to dump out frames until we get a new buffer
+-               * to use.
+-               */
+-              for (i = 0; i < num_nodes_streaming; i++) {
+-                      if (unicam->node[i].cur_frm)
+-                              unicam_process_buffer_complete(&unicam->node[i],
+-                                                             sequence);
+-                      unicam->node[i].cur_frm = unicam->node[i].next_frm;
+-              }
+-              unicam->sequence++;
+-      }
+-
+-      if (ista & UNICAM_FSI) {
+-              /*
+-               * Timestamp is to be when the first data byte was captured,
+-               * aka frame start.
+-               */
+-              ts = ktime_get_ns();
+-              for (i = 0; i < num_nodes_streaming; i++) {
+-                      if (unicam->node[i].cur_frm)
+-                              unicam->node[i].cur_frm->vb.vb2_buf.timestamp =
+-                                                              ts;
+-                      /*
+-                       * Set the next frame output to go to a dummy frame
+-                       * if we have not managed to obtain another frame
+-                       * from the queue.
+-                       */
+-                      unicam_schedule_dummy_buffer(&unicam->node[i]);
+-              }
+-
+-              unicam_queue_event_sof(unicam);
+-      }
+-      /*
+-       * Cannot swap buffer at frame end, there may be a race condition
+-       * where the HW does not actually swap it if the new frame has
+-       * already started.
+-       */
+-      if (ista & (UNICAM_FSI | UNICAM_LCI) && !(ista & UNICAM_FEI)) {
+-              for (i = 0; i < num_nodes_streaming; i++) {
+-                      spin_lock(&unicam->node[i].dma_queue_lock);
+-                      if (!list_empty(&unicam->node[i].dma_queue.active) &&
+-                          !unicam->node[i].next_frm)
+-                              unicam_schedule_next_buffer(&unicam->node[i]);
+-                      spin_unlock(&unicam->node[i].dma_queue_lock);
+-              }
+-      }
+-
+-      if (reg_read(&unicam->cfg, UNICAM_ICTL) & UNICAM_FCM) {
+-              /* Switch out of trigger mode if selected */
+-              reg_write_field(&unicam->cfg, UNICAM_ICTL, 1, UNICAM_TFC);
+-              reg_write_field(&unicam->cfg, UNICAM_ICTL, 0, UNICAM_FCM);
+-      }
+-      return IRQ_HANDLED;
+-}
+-
+-static int unicam_querycap(struct file *file, void *priv,
+-                         struct v4l2_capability *cap)
+-{
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-
+-      strlcpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
+-      strlcpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
+-
+-      snprintf(cap->bus_info, sizeof(cap->bus_info),
+-               "platform:%s", dev->v4l2_dev.name);
+-
+-      cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+-                          V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS |
+-                          V4L2_CAP_META_CAPTURE;
+-
+-      if (node->pad_id == IMAGE_PAD)
+-              cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+-      else
+-              cap->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;
+-
+-      return 0;
+-}
+-
+-static int unicam_enum_fmt_vid_cap(struct file *file, void  *priv,
+-                                 struct v4l2_fmtdesc *f)
+-{
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-      struct v4l2_subdev_mbus_code_enum mbus_code;
+-      const struct unicam_fmt *fmt = NULL;
+-      int index = 0;
+-      int ret = 0;
+-      int i;
+-
+-      if (node->pad_id == METADATA_PAD)
+-              return -EINVAL;
+-
+-      for (i = 0; !ret && i < MAX_ENUM_MBUS_CODE; i++) {
+-              memset(&mbus_code, 0, sizeof(mbus_code));
+-              mbus_code.index = i;
+-              mbus_code.pad = IMAGE_PAD;
+-              mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+-
+-              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code,
+-                                     NULL, &mbus_code);
+-              if (ret < 0) {
+-                      unicam_dbg(2, dev,
+-                                 "subdev->enum_mbus_code idx %d returned %d - index invalid\n",
+-                                 i, ret);
+-                      return -EINVAL;
+-              }
+-
+-              fmt = find_format_by_code(mbus_code.code);
+-              if (fmt) {
+-                      if (fmt->fourcc) {
+-                              if (index == f->index) {
+-                                      f->pixelformat = fmt->fourcc;
+-                                      break;
+-                              }
+-                              index++;
+-                      }
+-                      if (fmt->repacked_fourcc) {
+-                              if (index == f->index) {
+-                                      f->pixelformat = fmt->repacked_fourcc;
+-                                      break;
+-                              }
+-                              index++;
+-                      }
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+-static int unicam_g_fmt_vid_cap(struct file *file, void *priv,
+-                              struct v4l2_format *f)
+-{
+-      struct v4l2_mbus_framefmt mbus_fmt = {0};
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-      const struct unicam_fmt *fmt = NULL;
+-      int ret;
+-
+-      if (node->pad_id != IMAGE_PAD)
+-              return -EINVAL;
+-
+-      /*
+-       * If a flip has occurred in the sensor, the fmt code might have
+-       * changed. So we will need to re-fetch the format from the subdevice.
+-       */
+-      ret = __subdev_get_format(dev, &mbus_fmt, node->pad_id);
+-      if (ret)
+-              return -EINVAL;
+-
+-      /* Find the V4L2 format from mbus code. We must match a known format. */
+-      fmt = find_format_by_code(mbus_fmt.code);
+-      if (!fmt)
+-              return -EINVAL;
+-
+-      if (node->fmt != fmt) {
+-              /*
+-               * The sensor format has changed so the pixelformat needs to
+-               * be updated. Try and retain the packed/unpacked choice if
+-               * at all possible.
+-               */
+-              if (node->fmt->repacked_fourcc ==
+-                                              node->v_fmt.fmt.pix.pixelformat)
+-                      /* Using the repacked format */
+-                      node->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
+-              else
+-                      /* Using the native format */
+-                      node->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
+-
+-              node->fmt = fmt;
+-      }
+-
+-      *f = node->v_fmt;
+-
+-      return 0;
+-}
+-
+-static
+-const struct unicam_fmt *get_first_supported_format(struct unicam_device *dev)
+-{
+-      struct v4l2_subdev_mbus_code_enum mbus_code;
+-      const struct unicam_fmt *fmt = NULL;
+-      int ret = 0;
+-      int j;
+-
+-      for (j = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++j) {
+-              memset(&mbus_code, 0, sizeof(mbus_code));
+-              mbus_code.index = j;
+-              mbus_code.pad = IMAGE_PAD;
+-              mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+-
+-              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code, NULL,
+-                                     &mbus_code);
+-              if (ret < 0) {
+-                      unicam_dbg(2, dev,
+-                                 "subdev->enum_mbus_code idx %d returned %d - continue\n",
+-                                 j, ret);
+-                      continue;
+-              }
+-
+-              unicam_dbg(2, dev, "subdev %s: code: 0x%08x idx: %d\n",
+-                         dev->sensor->name, mbus_code.code, j);
+-
+-              fmt = find_format_by_code(mbus_code.code);
+-              unicam_dbg(2, dev, "fmt 0x%08x returned as %p, V4L2 FOURCC 0x%08x, csi_dt 0x%02x\n",
+-                         mbus_code.code, fmt, fmt ? fmt->fourcc : 0,
+-                         fmt ? fmt->csi_dt : 0);
+-              if (fmt)
+-                      return fmt;
+-      }
+-
+-      return NULL;
+-}
+-
+-static int unicam_try_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;
+-      struct v4l2_subdev_format sd_fmt = {
+-              .which = V4L2_SUBDEV_FORMAT_TRY,
+-              .pad = IMAGE_PAD
+-      };
+-      struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+-      const struct unicam_fmt *fmt;
+-      int ret;
+-
+-      if (node->pad_id == METADATA_PAD)
+-              return -EINVAL;
+-
+-      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
+-      if (!fmt) {
+-              /* Pixel format not supported by unicam. Choose the first
+-               * supported format, and let the sensor choose something else.
+-               */
+-              unicam_dbg(3, dev, "Fourcc format (0x%08x) not found. Use first format.\n",
+-                         f->fmt.pix.pixelformat);
+-
+-              fmt = &formats[0];
+-              f->fmt.pix.pixelformat = fmt->fourcc;
+-      }
+-
+-      v4l2_fill_mbus_format(mbus_fmt, &f->fmt.pix, fmt->code);
+-      /*
+-       * No support for receiving interlaced video, so never
+-       * request it from the sensor subdev.
+-       */
+-      mbus_fmt->field = V4L2_FIELD_NONE;
+-
+-      ret = v4l2_subdev_call(dev->sensor, pad, set_fmt, dev->sensor_config,
+-                             &sd_fmt);
+-      if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+-              return ret;
+-
+-      if (mbus_fmt->field != V4L2_FIELD_NONE)
+-              unicam_info(dev, "Sensor trying to send interlaced video - results may be unpredictable\n");
+-
+-      v4l2_fill_pix_format(&f->fmt.pix, &sd_fmt.format);
+-      if (mbus_fmt->code != fmt->code) {
+-              /* Sensor has returned an alternate format */
+-              fmt = find_format_by_code(mbus_fmt->code);
+-              if (!fmt) {
+-                      /* The alternate format is one unicam can't support.
+-                       * Find the first format that is supported by both, and
+-                       * then set that.
+-                       */
+-                      fmt = get_first_supported_format(dev);
+-                      mbus_fmt->code = fmt->code;
+-
+-                      ret = v4l2_subdev_call(dev->sensor, pad, set_fmt,
+-                                             dev->sensor_config, &sd_fmt);
+-                      if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+-                              return ret;
+-
+-                      if (mbus_fmt->field != V4L2_FIELD_NONE)
+-                              unicam_info(dev, "Sensor trying to send interlaced video - results may be unpredictable\n");
+-
+-                      v4l2_fill_pix_format(&f->fmt.pix, &sd_fmt.format);
+-
+-                      if (mbus_fmt->code != fmt->code) {
+-                              /* We've set a format that the sensor reports
+-                               * as being supported, but it refuses to set it.
+-                               * Not much else we can do.
+-                               * Assume that the sensor driver may accept the
+-                               * format when it is set (rather than tried).
+-                               */
+-                              unicam_err(dev, "Sensor won't accept default format, and Unicam can't support sensor default\n");
+-                      }
+-              }
+-
+-              if (fmt->fourcc)
+-                      f->fmt.pix.pixelformat = fmt->fourcc;
+-              else
+-                      f->fmt.pix.pixelformat = fmt->repacked_fourcc;
+-      }
+-
+-      return unicam_calc_format_size_bpl(dev, fmt, f);
+-}
+-
+-static int unicam_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;
+-      struct vb2_queue *q = &node->buffer_queue;
+-      struct v4l2_mbus_framefmt mbus_fmt = {0};
+-      const struct unicam_fmt *fmt;
+-      int ret;
+-
+-      if (vb2_is_busy(q))
+-              return -EBUSY;
+-
+-      ret = unicam_try_fmt_vid_cap(file, priv, f);
+-      if (ret < 0)
+-              return ret;
+-
+-      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
+-      if (!fmt) {
+-              /* Unknown pixel format - adopt a default.
+-               * This shouldn't happen as try_fmt should have resolved any
+-               * issues first.
+-               */
+-              fmt = get_first_supported_format(dev);
+-              if (!fmt)
+-                      /* It shouldn't be possible to get here with no
+-                       * supported formats
+-                       */
+-                      return -EINVAL;
+-              f->fmt.pix.pixelformat = fmt->fourcc;
+-              return -EINVAL;
+-      }
+-
+-      v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
+-
+-      ret = __subdev_set_format(dev, &mbus_fmt, node->pad_id);
+-      if (ret) {
+-              unicam_dbg(3, dev, "%s __subdev_set_format failed %d\n",
+-                         __func__, ret);
+-              return ret;
+-      }
+-
+-      /* Just double check nothing has gone wrong */
+-      if (mbus_fmt.code != fmt->code) {
+-              unicam_dbg(3, dev,
+-                         "%s subdev changed format on us, this should not happen\n",
+-                         __func__);
+-              return -EINVAL;
+-      }
+-
+-      node->fmt = fmt;
+-      node->v_fmt.fmt.pix.pixelformat = f->fmt.pix.pixelformat;
+-      node->v_fmt.fmt.pix.bytesperline = f->fmt.pix.bytesperline;
+-      unicam_reset_format(node);
+-
+-      unicam_dbg(3, dev,
+-                 "%s %dx%d, mbus_fmt 0x%08X, V4L2 pix 0x%08X.\n",
+-                 __func__, node->v_fmt.fmt.pix.width,
+-                 node->v_fmt.fmt.pix.height, mbus_fmt.code,
+-                 node->v_fmt.fmt.pix.pixelformat);
+-
+-      *f = node->v_fmt;
+-
+-      return 0;
+-}
+-
+-static int unicam_enum_fmt_meta_cap(struct file *file, void *priv,
+-                                  struct v4l2_fmtdesc *f)
+-{
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-      struct v4l2_subdev_mbus_code_enum mbus_code;
+-      const struct unicam_fmt *fmt = NULL;
+-      int ret = 0;
+-
+-      if (node->pad_id != METADATA_PAD || f->index != 0)
+-              return -EINVAL;
+-
+-      if (dev->sensor_embedded_data) {
+-              memset(&mbus_code, 0, sizeof(mbus_code));
+-              mbus_code.index = f->index;
+-              mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+-              mbus_code.pad = METADATA_PAD;
+-
+-              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code, NULL,
+-                                     &mbus_code);
+-              if (ret < 0) {
+-                      unicam_dbg(2, dev,
+-                                 "subdev->enum_mbus_code idx 0 returned %d - index invalid\n",
+-                                 ret);
+-                      return -EINVAL;
+-              }
+-      } else {
+-              mbus_code.code = MEDIA_BUS_FMT_SENSOR_DATA;
+-      }
+-
+-      fmt = find_format_by_code(mbus_code.code);
+-      if (fmt)
+-              f->pixelformat = fmt->fourcc;
+-
+-      return 0;
+-}
+-
+-static int unicam_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_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 = node->v_fmt;
+-
+-      return 0;
+-}
+-
+-static int unicam_s_fmt_meta_cap(struct file *file, void *priv,
+-                               struct v4l2_format *f)
+-{
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-      struct v4l2_mbus_framefmt mbus_fmt = { 0 };
+-      const struct unicam_fmt *fmt;
+-      int ret;
+-
+-      if (node->pad_id == IMAGE_PAD)
+-              return -EINVAL;
+-
+-      if (dev->sensor_embedded_data) {
+-              fmt = find_format_by_pix(dev, f->fmt.meta.dataformat);
+-              if (!fmt) {
+-                      unicam_err(dev, "unknown format: V4L2 pix 0x%08x\n",
+-                                 f->fmt.meta.dataformat);
+-                      return -EINVAL;
+-              }
+-              mbus_fmt.code = fmt->code;
+-              ret = __subdev_set_format(dev, &mbus_fmt, node->pad_id);
+-              if (ret) {
+-                      unicam_dbg(3, dev, "%s __subdev_set_format failed %d\n",
+-                                 __func__, ret);
+-                      return ret;
+-              }
+-      }
+-
+-      *f = node->v_fmt;
+-
+-      unicam_dbg(3, dev, "%s size %d, V4L2 pix 0x%08x\n",
+-                 __func__, node->v_fmt.fmt.meta.buffersize,
+-                 node->v_fmt.fmt.meta.dataformat);
+-
+-      return 0;
+-}
+-
+-static int unicam_queue_setup(struct vb2_queue *vq,
+-                            unsigned int *nbuffers,
+-                            unsigned int *nplanes,
+-                            unsigned int sizes[],
+-                            struct device *alloc_devs[])
+-{
+-      struct unicam_node *node = vb2_get_drv_priv(vq);
+-      struct unicam_device *dev = node->dev;
+-      unsigned int size = node->pad_id == IMAGE_PAD ?
+-                                  node->v_fmt.fmt.pix.sizeimage :
+-                                  node->v_fmt.fmt.meta.buffersize;
+-
+-      if (vq->num_buffers + *nbuffers < 3)
+-              *nbuffers = 3 - vq->num_buffers;
+-
+-      if (*nplanes) {
+-              if (sizes[0] < size) {
+-                      unicam_err(dev, "sizes[0] %i < size %u\n", sizes[0],
+-                                 size);
+-                      return -EINVAL;
+-              }
+-              size = sizes[0];
+-      }
+-
+-      *nplanes = 1;
+-      sizes[0] = size;
+-
+-      return 0;
+-}
+-
+-static int unicam_buffer_prepare(struct vb2_buffer *vb)
+-{
+-      struct unicam_node *node = vb2_get_drv_priv(vb->vb2_queue);
+-      struct unicam_device *dev = node->dev;
+-      struct unicam_buffer *buf = container_of(vb, struct unicam_buffer,
+-                                            vb.vb2_buf);
+-      unsigned long size;
+-
+-      if (WARN_ON(!node->fmt))
+-              return -EINVAL;
+-
+-      size = node->pad_id == IMAGE_PAD ? node->v_fmt.fmt.pix.sizeimage :
+-                                         node->v_fmt.fmt.meta.buffersize;
+-      if (vb2_plane_size(vb, 0) < size) {
+-              unicam_err(dev, "data will not fit into plane (%lu < %lu)\n",
+-                         vb2_plane_size(vb, 0), size);
+-              return -EINVAL;
+-      }
+-
+-      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
+-      return 0;
+-}
+-
+-static void unicam_buffer_queue(struct vb2_buffer *vb)
+-{
+-      struct unicam_node *node = vb2_get_drv_priv(vb->vb2_queue);
+-      struct unicam_buffer *buf = container_of(vb, struct unicam_buffer,
+-                                            vb.vb2_buf);
+-      struct unicam_dmaqueue *dma_queue = &node->dma_queue;
+-      unsigned long flags = 0;
+-
+-      spin_lock_irqsave(&node->dma_queue_lock, flags);
+-      list_add_tail(&buf->list, &dma_queue->active);
+-      spin_unlock_irqrestore(&node->dma_queue_lock, flags);
+-}
+-
+-static void unicam_set_packing_config(struct unicam_device *dev)
+-{
+-      int pack, unpack;
+-      u32 val;
+-
+-      if (dev->node[IMAGE_PAD].v_fmt.fmt.pix.pixelformat ==
+-          dev->node[IMAGE_PAD].fmt->fourcc) {
+-              unpack = UNICAM_PUM_NONE;
+-              pack = UNICAM_PPM_NONE;
+-      } else {
+-              switch (dev->node[IMAGE_PAD].fmt->depth) {
+-              case 8:
+-                      unpack = UNICAM_PUM_UNPACK8;
+-                      break;
+-              case 10:
+-                      unpack = UNICAM_PUM_UNPACK10;
+-                      break;
+-              case 12:
+-                      unpack = UNICAM_PUM_UNPACK12;
+-                      break;
+-              case 14:
+-                      unpack = UNICAM_PUM_UNPACK14;
+-                      break;
+-              case 16:
+-                      unpack = UNICAM_PUM_UNPACK16;
+-                      break;
+-              default:
+-                      unpack = UNICAM_PUM_NONE;
+-                      break;
+-              }
+-
+-              /* Repacking is always to 16bpp */
+-              pack = UNICAM_PPM_PACK16;
+-      }
+-
+-      val = 0;
+-      set_field(&val, unpack, UNICAM_PUM_MASK);
+-      set_field(&val, pack, UNICAM_PPM_MASK);
+-      reg_write(&dev->cfg, UNICAM_IPIPE, val);
+-}
+-
+-static void unicam_cfg_image_id(struct unicam_device *dev)
+-{
+-      struct unicam_cfg *cfg = &dev->cfg;
+-
+-      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
+-              /* CSI2 mode */
+-              reg_write(cfg, UNICAM_IDI0,
+-                        (dev->virtual_channel << 6) |
+-                                            dev->node[IMAGE_PAD].fmt->csi_dt);
+-      } else {
+-              /* CCP2 mode */
+-              reg_write(cfg, UNICAM_IDI0,
+-                        0x80 | dev->node[IMAGE_PAD].fmt->csi_dt);
+-      }
+-}
+-
+-static void unicam_enable_ed(struct unicam_device *dev)
+-{
+-      struct unicam_cfg *cfg = &dev->cfg;
+-      u32 val = reg_read(cfg, UNICAM_DCS);
+-
+-      set_field(&val, 2, UNICAM_EDL_MASK);
+-      /* Do not wrap at the end of the embedded data buffer */
+-      set_field(&val, 0, UNICAM_DBOB);
+-
+-      reg_write(cfg, UNICAM_DCS, val);
+-}
+-
+-static void unicam_start_rx(struct unicam_device *dev, dma_addr_t *addr)
+-{
+-      struct unicam_cfg *cfg = &dev->cfg;
+-      int line_int_freq = dev->node[IMAGE_PAD].v_fmt.fmt.pix.height >> 2;
+-      unsigned int size, i;
+-      u32 val;
+-
+-      if (line_int_freq < 128)
+-              line_int_freq = 128;
+-
+-      /* Enable lane clocks */
+-      val = 1;
+-      for (i = 0; i < dev->active_data_lanes; i++)
+-              val = val << 2 | 1;
+-      clk_write(cfg, val);
+-
+-      /* Basic init */
+-      reg_write(cfg, UNICAM_CTRL, UNICAM_MEM);
+-
+-      /* Enable analogue control, and leave in reset. */
+-      val = UNICAM_AR;
+-      set_field(&val, 7, UNICAM_CTATADJ_MASK);
+-      set_field(&val, 7, UNICAM_PTATADJ_MASK);
+-      reg_write(cfg, UNICAM_ANA, val);
+-      usleep_range(1000, 2000);
+-
+-      /* Come out of reset */
+-      reg_write_field(cfg, UNICAM_ANA, 0, UNICAM_AR);
+-
+-      /* Peripheral reset */
+-      reg_write_field(cfg, UNICAM_CTRL, 1, UNICAM_CPR);
+-      reg_write_field(cfg, UNICAM_CTRL, 0, UNICAM_CPR);
+-
+-      reg_write_field(cfg, UNICAM_CTRL, 0, UNICAM_CPE);
+-
+-      /* Enable Rx control. */
+-      val = reg_read(cfg, UNICAM_CTRL);
+-      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
+-              set_field(&val, UNICAM_CPM_CSI2, UNICAM_CPM_MASK);
+-              set_field(&val, UNICAM_DCM_STROBE, UNICAM_DCM_MASK);
+-      } else {
+-              set_field(&val, UNICAM_CPM_CCP2, UNICAM_CPM_MASK);
+-              set_field(&val, dev->bus_flags, UNICAM_DCM_MASK);
+-      }
+-      /* Packet framer timeout */
+-      set_field(&val, 0xf, UNICAM_PFT_MASK);
+-      set_field(&val, 128, UNICAM_OET_MASK);
+-      reg_write(cfg, UNICAM_CTRL, val);
+-
+-      reg_write(cfg, UNICAM_IHWIN, 0);
+-      reg_write(cfg, UNICAM_IVWIN, 0);
+-
+-      /* AXI bus access QoS setup */
+-      val = reg_read(&dev->cfg, UNICAM_PRI);
+-      set_field(&val, 0, UNICAM_BL_MASK);
+-      set_field(&val, 0, UNICAM_BS_MASK);
+-      set_field(&val, 0xe, UNICAM_PP_MASK);
+-      set_field(&val, 8, UNICAM_NP_MASK);
+-      set_field(&val, 2, UNICAM_PT_MASK);
+-      set_field(&val, 1, UNICAM_PE);
+-      reg_write(cfg, UNICAM_PRI, val);
+-
+-      reg_write_field(cfg, UNICAM_ANA, 0, UNICAM_DDL);
+-
+-      /* Always start in trigger frame capture mode (UNICAM_FCM set) */
+-      val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_FCM | UNICAM_IBOB;
+-      set_field(&val,  line_int_freq, UNICAM_LCIE_MASK);
+-      reg_write(cfg, UNICAM_ICTL, val);
+-      reg_write(cfg, UNICAM_STA, UNICAM_STA_MASK_ALL);
+-      reg_write(cfg, UNICAM_ISTA, UNICAM_ISTA_MASK_ALL);
+-
+-      /* tclk_term_en */
+-      reg_write_field(cfg, UNICAM_CLT, 2, UNICAM_CLT1_MASK);
+-      /* tclk_settle */
+-      reg_write_field(cfg, UNICAM_CLT, 6, UNICAM_CLT2_MASK);
+-      /* td_term_en */
+-      reg_write_field(cfg, UNICAM_DLT, 2, UNICAM_DLT1_MASK);
+-      /* ths_settle */
+-      reg_write_field(cfg, UNICAM_DLT, 6, UNICAM_DLT2_MASK);
+-      /* trx_enable */
+-      reg_write_field(cfg, UNICAM_DLT, 0, UNICAM_DLT3_MASK);
+-
+-      reg_write_field(cfg, UNICAM_CTRL, 0, UNICAM_SOE);
+-
+-      /* Packet compare setup - required to avoid missing frame ends */
+-      val = 0;
+-      set_field(&val, 1, UNICAM_PCE);
+-      set_field(&val, 1, UNICAM_GI);
+-      set_field(&val, 1, UNICAM_CPH);
+-      set_field(&val, 0, UNICAM_PCVC_MASK);
+-      set_field(&val, 1, UNICAM_PCDT_MASK);
+-      reg_write(cfg, UNICAM_CMP0, val);
+-
+-      /* Enable clock lane and set up terminations */
+-      val = 0;
+-      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
+-              /* CSI2 */
+-              set_field(&val, 1, UNICAM_CLE);
+-              set_field(&val, 1, UNICAM_CLLPE);
+-              if (dev->bus_flags & V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) {
+-                      set_field(&val, 1, UNICAM_CLTRE);
+-                      set_field(&val, 1, UNICAM_CLHSE);
+-              }
+-      } else {
+-              /* CCP2 */
+-              set_field(&val, 1, UNICAM_CLE);
+-              set_field(&val, 1, UNICAM_CLHSE);
+-              set_field(&val, 1, UNICAM_CLTRE);
+-      }
+-      reg_write(cfg, UNICAM_CLK, val);
+-
+-      /*
+-       * Enable required data lanes with appropriate terminations.
+-       * The same value needs to be written to UNICAM_DATn registers for
+-       * the active lanes, and 0 for inactive ones.
+-       */
+-      val = 0;
+-      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
+-              /* CSI2 */
+-              set_field(&val, 1, UNICAM_DLE);
+-              set_field(&val, 1, UNICAM_DLLPE);
+-              if (dev->bus_flags & V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) {
+-                      set_field(&val, 1, UNICAM_DLTRE);
+-                      set_field(&val, 1, UNICAM_DLHSE);
+-              }
+-      } else {
+-              /* CCP2 */
+-              set_field(&val, 1, UNICAM_DLE);
+-              set_field(&val, 1, UNICAM_DLHSE);
+-              set_field(&val, 1, UNICAM_DLTRE);
+-      }
+-      reg_write(cfg, UNICAM_DAT0, val);
+-
+-      if (dev->active_data_lanes == 1)
+-              val = 0;
+-      reg_write(cfg, UNICAM_DAT1, val);
+-
+-      if (dev->max_data_lanes > 2) {
+-              /*
+-               * Registers UNICAM_DAT2 and UNICAM_DAT3 only valid if the
+-               * instance supports more than 2 data lanes.
+-               */
+-              if (dev->active_data_lanes == 2)
+-                      val = 0;
+-              reg_write(cfg, UNICAM_DAT2, val);
+-
+-              if (dev->active_data_lanes == 3)
+-                      val = 0;
+-              reg_write(cfg, UNICAM_DAT3, val);
+-      }
+-
+-      reg_write(&dev->cfg, UNICAM_IBLS,
+-                dev->node[IMAGE_PAD].v_fmt.fmt.pix.bytesperline);
+-      size = dev->node[IMAGE_PAD].v_fmt.fmt.pix.sizeimage;
+-      unicam_wr_dma_addr(&dev->cfg, addr[IMAGE_PAD], size, IMAGE_PAD);
+-      unicam_set_packing_config(dev);
+-      unicam_cfg_image_id(dev);
+-
+-      val = reg_read(cfg, UNICAM_MISC);
+-      set_field(&val, 1, UNICAM_FL0);
+-      set_field(&val, 1, UNICAM_FL1);
+-      reg_write(cfg, UNICAM_MISC, val);
+-
+-      if (dev->node[METADATA_PAD].streaming && dev->sensor_embedded_data) {
+-              size = dev->node[METADATA_PAD].v_fmt.fmt.meta.buffersize;
+-              unicam_enable_ed(dev);
+-              unicam_wr_dma_addr(&dev->cfg, addr[METADATA_PAD], size,
+-                                 METADATA_PAD);
+-      }
+-
+-      /* Enable peripheral */
+-      reg_write_field(cfg, UNICAM_CTRL, 1, UNICAM_CPE);
+-
+-      /* Load image pointers */
+-      reg_write_field(cfg, UNICAM_ICTL, 1, UNICAM_LIP_MASK);
+-
+-      /* Load embedded data buffer pointers if needed */
+-      if (dev->node[METADATA_PAD].streaming && dev->sensor_embedded_data)
+-              reg_write_field(cfg, UNICAM_DCS, 1, UNICAM_LDP);
+-
+-      /*
+-       * Enable trigger only for the first frame to
+-       * sync correctly to the FS from the source.
+-       */
+-      reg_write_field(cfg, UNICAM_ICTL, 1, UNICAM_TFC);
+-}
+-
+-static void unicam_disable(struct unicam_device *dev)
+-{
+-      struct unicam_cfg *cfg = &dev->cfg;
+-
+-      /* Analogue lane control disable */
+-      reg_write_field(cfg, UNICAM_ANA, 1, UNICAM_DDL);
+-
+-      /* Stop the output engine */
+-      reg_write_field(cfg, UNICAM_CTRL, 1, UNICAM_SOE);
+-
+-      /* Disable the data lanes. */
+-      reg_write(cfg, UNICAM_DAT0, 0);
+-      reg_write(cfg, UNICAM_DAT1, 0);
+-
+-      if (dev->max_data_lanes > 2) {
+-              reg_write(cfg, UNICAM_DAT2, 0);
+-              reg_write(cfg, UNICAM_DAT3, 0);
+-      }
+-
+-      /* Peripheral reset */
+-      reg_write_field(cfg, UNICAM_CTRL, 1, UNICAM_CPR);
+-      usleep_range(50, 100);
+-      reg_write_field(cfg, UNICAM_CTRL, 0, UNICAM_CPR);
+-
+-      /* Disable peripheral */
+-      reg_write_field(cfg, UNICAM_CTRL, 0, UNICAM_CPE);
+-
+-      /* Clear ED setup */
+-      reg_write(cfg, UNICAM_DCS, 0);
+-
+-      /* Disable all lane clocks */
+-      clk_write(cfg, 0);
+-}
+-
+-static int unicam_start_streaming(struct vb2_queue *vq, unsigned int count)
+-{
+-      struct unicam_node *node = vb2_get_drv_priv(vq);
+-      struct unicam_device *dev = node->dev;
+-      struct unicam_buffer *buf;
+-      dma_addr_t buffer_addr[MAX_NODES] = { 0 };
+-      int num_nodes_streaming;
+-      unsigned long flags;
+-      int ret, i;
+-
+-      node->streaming = 1;
+-      if (!unicam_all_nodes_streaming(dev)) {
+-              unicam_dbg(3, dev, "Not all nodes are streaming yet.");
+-              return 0;
+-      }
+-
+-      dev->sequence = 0;
+-      ret = unicam_runtime_get(dev);
+-      if (ret < 0) {
+-              unicam_dbg(3, dev, "unicam_runtime_get failed\n");
+-              return ret;
+-      }
+-
+-      dev->active_data_lanes = dev->max_data_lanes;
+-      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY &&
+-          v4l2_subdev_has_op(dev->sensor, video, g_mbus_config)) {
+-              struct v4l2_mbus_config mbus_config;
+-
+-              ret = v4l2_subdev_call(dev->sensor, video, g_mbus_config,
+-                                     &mbus_config);
+-              if (ret < 0) {
+-                      unicam_dbg(3, dev, "g_mbus_config failed\n");
+-                      goto err_pm_put;
+-              }
+-
+-              dev->active_data_lanes =
+-                      (mbus_config.flags & V4L2_MBUS_CSI2_LANE_MASK) >>
+-                                      __ffs(V4L2_MBUS_CSI2_LANE_MASK);
+-              if (!dev->active_data_lanes)
+-                      dev->active_data_lanes = dev->max_data_lanes;
+-      }
+-      if (dev->active_data_lanes > dev->max_data_lanes) {
+-              unicam_err(dev, "Device has requested %u data lanes, which is >%u configured in DT\n",
+-                         dev->active_data_lanes, dev->max_data_lanes);
+-              ret = -EINVAL;
+-              goto err_pm_put;
+-      }
+-
+-      unicam_dbg(1, dev, "Running with %u data lanes\n",
+-                 dev->active_data_lanes);
+-
+-      ret = clk_set_rate(dev->clock, 100 * 1000 * 1000);
+-      if (ret) {
+-              unicam_err(dev, "failed to set up clock\n");
+-              goto err_pm_put;
+-      }
+-
+-      ret = clk_prepare_enable(dev->clock);
+-      if (ret) {
+-              unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
+-              goto err_pm_put;
+-      }
+-
+-      num_nodes_streaming = unicam_num_nodes_streaming(dev);
+-      for (i = 0; i < num_nodes_streaming; i++) {
+-              spin_lock_irqsave(&dev->node[i].dma_queue_lock, flags);
+-              buf = list_entry(dev->node[i].dma_queue.active.next,
+-                               struct unicam_buffer, list);
+-              dev->node[i].cur_frm = buf;
+-              dev->node[i].next_frm = buf;
+-              list_del(&buf->list);
+-              spin_unlock_irqrestore(&dev->node[i].dma_queue_lock, flags);
+-              buffer_addr[i] =
+-              vb2_dma_contig_plane_dma_addr(&dev->node[i].cur_frm->vb.vb2_buf,
+-                                            0);
+-      }
+-
+-      unicam_start_rx(dev, buffer_addr);
+-
+-      ret = v4l2_subdev_call(dev->sensor, video, s_stream, 1);
+-      if (ret < 0) {
+-              unicam_err(dev, "stream on failed in subdev\n");
+-              goto err_disable_unicam;
+-      }
+-
+-      return 0;
+-
+-err_disable_unicam:
+-      node->streaming = 0;
+-      unicam_disable(dev);
+-      clk_disable_unprepare(dev->clock);
+-err_pm_put:
+-      unicam_runtime_put(dev);
+-
+-      return ret;
+-}
+-
+-static void unicam_stop_streaming(struct vb2_queue *vq)
+-{
+-      struct unicam_node *node = vb2_get_drv_priv(vq);
+-      struct unicam_device *dev = node->dev;
+-      struct unicam_dmaqueue *dma_q = &node->dma_queue;
+-      struct unicam_buffer *buf, *tmp;
+-      unsigned long flags;
+-
+-      node->streaming = 0;
+-
+-      if (node->pad_id == IMAGE_PAD) {
+-              /* Stop streaming the sensor and disable the peripheral.
+-               * We cannot continue streaming embedded data with the
+-               * image pad disabled.
+-               */
+-              if (v4l2_subdev_call(dev->sensor, video, s_stream, 0) < 0)
+-                      unicam_err(dev, "stream off failed in subdev\n");
+-
+-              unicam_disable(dev);
+-              clk_disable_unprepare(dev->clock);
+-              unicam_runtime_put(dev);
+-
+-      } else if (node->pad_id == METADATA_PAD) {
+-              /* Allow the hardware to spin in the dummy buffer.
+-               * This is only really needed if the embedded data pad is
+-               * disabled before the image pad.  The 0x3 in the top two bits
+-               * signifies uncached accesses through the Videocore memory
+-               * controller.
+-               */
+-              unicam_wr_dma_addr(&dev->cfg, node->dummy_buf_dma_addr,
+-                                 DUMMY_BUF_SIZE, METADATA_PAD);
+-      }
+-
+-      /* Clear all queued buffers for the node */
+-      spin_lock_irqsave(&node->dma_queue_lock, flags);
+-      list_for_each_entry_safe(buf, tmp, &dma_q->active, list) {
+-              list_del(&buf->list);
+-              vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+-      }
+-
+-      if (node->cur_frm)
+-              vb2_buffer_done(&node->cur_frm->vb.vb2_buf,
+-                              VB2_BUF_STATE_ERROR);
+-      if (node->next_frm && node->cur_frm != node->next_frm)
+-              vb2_buffer_done(&node->next_frm->vb.vb2_buf,
+-                              VB2_BUF_STATE_ERROR);
+-
+-      node->cur_frm = NULL;
+-      node->next_frm = NULL;
+-      spin_unlock_irqrestore(&node->dma_queue_lock, flags);
+-}
+-
+-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;
+-
+-      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;
+-      }
+-      sprintf(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, &current_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,
+-      };
+-
+-      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;
+-
+-      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;
+-
+-      if (node->pad_id == IMAGE_PAD) {
+-              /* 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;
+-      } else {
+-              /* This pad is for embedded data, so just set the format */
+-              fse.code = MEDIA_BUS_FMT_SENSOR_DATA;
+-      }
+-
+-      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,
+-                             &current_timings);
+-
+-      if (v4l2_match_dv_timings(timings, &current_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;
+-      struct unicam_cfg *cfg = &dev->cfg;
+-      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->cfg, 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(cfg, UNICAM_IBLS));
+-      unicam_info(dev, "Detected resolution: %ux%u\n",
+-                  reg_read(cfg, UNICAM_IHSTA),
+-                  reg_read(cfg, UNICAM_IVSTA));
+-      unicam_info(dev, "Write pointer:       %08x\n",
+-                  reg_read(cfg, UNICAM_IBWP));
+-
+-      return 0;
+-}
+-
+-static void unicam_notify(struct v4l2_subdev *sd,
+-                        unsigned int notification, void *arg)
+-{
+-      struct unicam_device *dev =
+-              container_of(sd->v4l2_dev, struct unicam_device, 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,
+-      .wait_finish            = vb2_ops_wait_finish,
+-      .queue_setup            = unicam_queue_setup,
+-      .buf_prepare            = unicam_buffer_prepare,
+-      .buf_queue              = unicam_buffer_queue,
+-      .start_streaming        = unicam_start_streaming,
+-      .stop_streaming         = unicam_stop_streaming,
+-};
+-
+-/*
+- * unicam_open : This function is based on the v4l2_fh_open helper function.
+- * It has been augmented to handle sensor subdevice power management,
+- */
+-static int unicam_open(struct file *file)
+-{
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-      int ret;
+-
+-      mutex_lock(&node->lock);
+-
+-      ret = v4l2_fh_open(file);
+-      if (ret) {
+-              unicam_err(dev, "v4l2_fh_open failed\n");
+-              goto unlock;
+-      }
+-
+-      node->open++;
+-
+-      if (!v4l2_fh_is_singular_file(file))
+-              goto unlock;
+-
+-      ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
+-      if (ret < 0 && ret != -ENOIOCTLCMD) {
+-              v4l2_fh_release(file);
+-              node->open--;
+-              goto unlock;
+-      }
+-
+-      ret = 0;
+-
+-unlock:
+-      mutex_unlock(&node->lock);
+-      return ret;
+-}
+-
+-static int unicam_release(struct file *file)
+-{
+-      struct unicam_node *node = video_drvdata(file);
+-      struct unicam_device *dev = node->dev;
+-      struct v4l2_subdev *sd = dev->sensor;
+-      bool fh_singular;
+-      int ret;
+-
+-      mutex_lock(&node->lock);
+-
+-      fh_singular = v4l2_fh_is_singular_file(file);
+-
+-      ret = _vb2_fop_release(file, NULL);
+-
+-      if (fh_singular)
+-              v4l2_subdev_call(sd, core, s_power, 0);
+-
+-      node->open--;
+-      mutex_unlock(&node->lock);
+-
+-      return ret;
+-}
+-
+-/* unicam capture driver file operations */
+-static const struct v4l2_file_operations unicam_fops = {
+-      .owner          = THIS_MODULE,
+-      .open           = unicam_open,
+-      .release        = unicam_release,
+-      .read           = vb2_fop_read,
+-      .poll           = vb2_fop_poll,
+-      .unlocked_ioctl = video_ioctl2,
+-      .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_s_fmt_meta_cap,
+-      .vidioc_try_fmt_meta_cap        = unicam_try_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,
+-                 struct v4l2_async_subdev *asd)
+-{
+-      struct unicam_device *unicam = container_of(notifier->v4l2_dev,
+-                                             struct unicam_device, v4l2_dev);
+-
+-      if (unicam->sensor) {
+-              unicam_info(unicam, "Rejecting subdev %s (Already set!!)",
+-                          subdev->name);
+-              return 0;
+-      }
+-
+-      unicam->sensor = subdev;
+-      unicam_dbg(1, unicam, "Using sensor %s for capture\n", subdev->name);
+-
+-      return 0;
+-}
+-
+-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;
+-      struct v4l2_mbus_framefmt mbus_fmt = {0};
+-      const struct unicam_fmt *fmt;
+-      int ret;
+-
+-      if (unicam->sensor_embedded_data || pad_id != METADATA_PAD) {
+-              ret = __subdev_get_format(unicam, &mbus_fmt, pad_id);
+-              if (ret) {
+-                      unicam_err(unicam, "Failed to get_format - ret %d\n",
+-                                 ret);
+-                      return ret;
+-              }
+-
+-              fmt = find_format_by_code(mbus_fmt.code);
+-              if (!fmt) {
+-                      /* Find the first format that the sensor and unicam both
+-                       * support
+-                       */
+-                      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 (mbus_fmt.field != V4L2_FIELD_NONE) {
+-                      /* Interlaced not supported - disable it now. */
+-                      mbus_fmt.field = V4L2_FIELD_NONE;
+-                      ret = __subdev_set_format(unicam, &mbus_fmt, pad_id);
+-                      if (ret)
+-                              return -EINVAL;
+-              }
+-      } else {
+-              /* Fix this node format as embedded data. */
+-              fmt = find_format_by_code(MEDIA_BUS_FMT_SENSOR_DATA);
+-      }
+-
+-      node->dev = unicam;
+-      node->pad_id = pad_id;
+-      node->fmt = fmt;
+-      if (fmt->fourcc) {
+-              if (fmt->fourcc != V4L2_META_FMT_SENSOR_DATA)
+-                      node->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
+-              else
+-                      node->v_fmt.fmt.meta.dataformat = fmt->fourcc;
+-      } else {
+-              node->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
+-      }
+-
+-      /* Read current subdev format */
+-      unicam_reset_format(node);
+-
+-      if (v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
+-              v4l2_std_id tvnorms;
+-
+-              if (WARN_ON(!v4l2_subdev_has_op(unicam->sensor, video,
+-                                              g_tvnorms)))
+-                      /*
+-                       * Subdevice should not advertise s_std but not
+-                       * g_tvnorms
+-                       */
+-                      return -EINVAL;
+-
+-              ret = v4l2_subdev_call(unicam->sensor, video,
+-                                     g_tvnorms, &tvnorms);
+-              if (WARN_ON(ret))
+-                      return -EINVAL;
+-              node->video_dev.tvnorms |= tvnorms;
+-      }
+-
+-      spin_lock_init(&node->dma_queue_lock);
+-      mutex_init(&node->lock);
+-
+-      vdev = &node->video_dev;
+-      if (pad_id == IMAGE_PAD) {
+-              /* Add controls from the subdevice */
+-              ret = v4l2_ctrl_add_handler(&node->ctrl_handler,
+-                                          unicam->sensor->ctrl_handler, NULL,
+-                                          true);
+-              if (ret < 0)
+-                      return ret;
+-
+-              /*
+-               * If the sensor subdevice has any controls, associate the node
+-               *  with the ctrl handler to allow access from userland.
+-               */
+-              if (!list_empty(&node->ctrl_handler.ctrls))
+-                      vdev->ctrl_handler = &node->ctrl_handler;
+-      }
+-
+-      q = &node->buffer_queue;
+-      q->type = type;
+-      q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+-      q->drv_priv = node;
+-      q->ops = &unicam_video_qops;
+-      q->mem_ops = &vb2_dma_contig_memops;
+-      q->buf_struct_size = sizeof(struct unicam_buffer);
+-      q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+-      q->lock = &node->lock;
+-      q->min_buffers_needed = 1;
+-      q->dev = &unicam->pdev->dev;
+-
+-      ret = vb2_queue_init(q);
+-      if (ret) {
+-              unicam_err(unicam, "vb2_queue_init() failed\n");
+-              return ret;
+-      }
+-
+-      INIT_LIST_HEAD(&node->dma_queue.active);
+-
+-      vdev->release = video_device_release_empty;
+-      vdev->fops = &unicam_fops;
+-      vdev->ioctl_ops = &unicam_ioctl_ops;
+-      vdev->v4l2_dev = &unicam->v4l2_dev;
+-      vdev->vfl_dir = VFL_DIR_RX;
+-      vdev->queue = q;
+-      vdev->lock = &node->lock;
+-      vdev->device_caps = (pad_id == IMAGE_PAD) ?
+-                          (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING) :
+-                          (V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING);
+-
+-      /* Define the device names */
+-      snprintf(vdev->name, sizeof(vdev->name), "%s-%s", UNICAM_MODULE_NAME,
+-               node->pad_id == IMAGE_PAD ? "image" : "embedded");
+-
+-      video_set_drvdata(vdev, node);
+-      vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
+-
+-      node->dummy_buf_cpu_addr = dma_alloc_coherent(&unicam->pdev->dev,
+-                                                    DUMMY_BUF_SIZE,
+-                                                    &node->dummy_buf_dma_addr,
+-                                                    GFP_ATOMIC);
+-      if (!node->dummy_buf_cpu_addr) {
+-              unicam_err(unicam, "Unable to allocate dummy buffer.\n");
+-              return -ENOMEM;
+-      }
+-
+-      if (node->pad_id == METADATA_PAD) {
+-              v4l2_disable_ioctl(vdev, VIDIOC_DQEVENT);
+-              v4l2_disable_ioctl(vdev, VIDIOC_SUBSCRIBE_EVENT);
+-              v4l2_disable_ioctl(vdev, VIDIOC_UNSUBSCRIBE_EVENT);
+-      }
+-      if (node->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 (node->pad_id == METADATA_PAD ||
+-          !v4l2_subdev_has_op(unicam->sensor, video, querystd))
+-              v4l2_disable_ioctl(&node->video_dev, VIDIOC_QUERYSTD);
+-      if (node->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 (node->pad_id == METADATA_PAD ||
+-          !v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_interval))
+-              v4l2_disable_ioctl(&node->video_dev,
+-                                 VIDIOC_ENUM_FRAMEINTERVALS);
+-      if (node->pad_id == METADATA_PAD ||
+-          !v4l2_subdev_has_op(unicam->sensor, video, g_frame_interval))
+-              v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_PARM);
+-      if (node->pad_id == METADATA_PAD ||
+-          !v4l2_subdev_has_op(unicam->sensor, video, s_frame_interval))
+-              v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_PARM);
+-
+-      if (node->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_GRABBER, -1);
+-      if (ret) {
+-              unicam_err(unicam, "Unable to register video device.\n");
+-              return ret;
+-      }
+-      node->registered = 1;
+-
+-      if (unicam->sensor_embedded_data) {
+-              ret = media_create_pad_link(&unicam->sensor->entity, pad_id,
+-                                          &node->video_dev.entity, 0,
+-                                          MEDIA_LNK_FL_ENABLED |
+-                                          MEDIA_LNK_FL_IMMUTABLE);
+-              if (ret)
+-                      unicam_err(unicam, "Unable to create pad links.\n");
+-      }
+-
+-      return ret;
+-}
+-
+-static void unregister_nodes(struct unicam_device *unicam)
+-{
+-      struct unicam_node *node;
+-      int i;
+-
+-      for (i = 0; i < MAX_NODES; i++) {
+-              node = &unicam->node[i];
+-              if (node->dummy_buf_cpu_addr) {
+-                      dma_free_coherent(&unicam->pdev->dev, DUMMY_BUF_SIZE,
+-                                        node->dummy_buf_cpu_addr,
+-                                        node->dummy_buf_dma_addr);
+-              }
+-              if (node->registered) {
+-                      video_unregister_device(&node->video_dev);
+-                      node->registered = 0;
+-              }
+-      }
+-}
+-
+-static int unicam_probe_complete(struct unicam_device *unicam)
+-{
+-      int ret;
+-
+-      v4l2_set_subdev_hostdata(unicam->sensor, unicam);
+-
+-      unicam->v4l2_dev.notify = unicam_notify;
+-
+-      unicam->sensor_config = v4l2_subdev_alloc_pad_config(unicam->sensor);
+-      if (!unicam->sensor_config)
+-              return -ENOMEM;
+-
+-      unicam->sensor_embedded_data = (unicam->sensor->entity.num_pads >= 2);
+-
+-      ret = register_node(unicam, &unicam->node[IMAGE_PAD],
+-                          V4L2_BUF_TYPE_VIDEO_CAPTURE, IMAGE_PAD);
+-      if (ret) {
+-              unicam_err(unicam, "Unable to register subdev node 0.\n");
+-              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 subdev node 1.\n");
+-              goto unregister;
+-      }
+-
+-      ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev);
+-      if (ret) {
+-              unicam_err(unicam, "Unable to register subdev nodes.\n");
+-              goto unregister;
+-      }
+-
+-      return 0;
+-
+-unregister:
+-      unregister_nodes(unicam);
+-
+-      return ret;
+-}
+-
+-static int unicam_async_complete(struct v4l2_async_notifier *notifier)
+-{
+-      struct unicam_device *unicam = container_of(notifier->v4l2_dev,
+-                                      struct unicam_device, 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,
+-};
+-
+-static int of_unicam_connect_subdevs(struct unicam_device *dev)
+-{
+-      struct platform_device *pdev = dev->pdev;
+-      struct device_node *parent, *ep_node = NULL, *remote_ep = NULL,
+-                      *sensor_node = NULL;
+-      struct v4l2_fwnode_endpoint *ep;
+-      struct v4l2_async_subdev *asd;
+-      unsigned int peripheral_data_lanes;
+-      int ret = -EINVAL;
+-      unsigned int lane;
+-
+-      parent = pdev->dev.of_node;
+-
+-      asd = &dev->asd;
+-      ep = &dev->endpoint;
+-
+-      ep_node = of_graph_get_next_endpoint(parent, NULL);
+-      if (!ep_node) {
+-              unicam_dbg(3, dev, "can't get next endpoint\n");
+-              goto cleanup_exit;
+-      }
+-
+-      unicam_dbg(3, dev, "ep_node is %s\n", ep_node->name);
+-
+-      v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), ep);
+-
+-      for (lane = 0; lane < ep->bus.mipi_csi2.num_data_lanes; lane++) {
+-              if (ep->bus.mipi_csi2.data_lanes[lane] != lane + 1) {
+-                      unicam_err(dev, "Local endpoint - data lane reordering not supported\n");
+-                      goto cleanup_exit;
+-              }
+-      }
+-
+-      peripheral_data_lanes = ep->bus.mipi_csi2.num_data_lanes;
+-
+-      sensor_node = of_graph_get_remote_port_parent(ep_node);
+-      if (!sensor_node) {
+-              unicam_dbg(3, dev, "can't get remote parent\n");
+-              goto cleanup_exit;
+-      }
+-      unicam_dbg(3, dev, "sensor_node is %s\n", sensor_node->name);
+-      asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
+-      asd->match.fwnode = of_fwnode_handle(sensor_node);
+-
+-      remote_ep = of_graph_get_remote_endpoint(ep_node);
+-      if (!remote_ep) {
+-              unicam_dbg(3, dev, "can't get remote-endpoint\n");
+-              goto cleanup_exit;
+-      }
+-      unicam_dbg(3, dev, "remote_ep is %s\n", remote_ep->name);
+-      v4l2_fwnode_endpoint_parse(of_fwnode_handle(remote_ep), ep);
+-      unicam_dbg(3, dev, "parsed remote_ep to endpoint. nr_of_link_frequencies %u, bus_type %u\n",
+-                 ep->nr_of_link_frequencies, ep->bus_type);
+-
+-      switch (ep->bus_type) {
+-      case V4L2_MBUS_CSI2_DPHY:
+-              if (ep->bus.mipi_csi2.num_data_lanes >
+-                              peripheral_data_lanes) {
+-                      unicam_err(dev, "Subdevice %s wants too many data lanes (%u > %u)\n",
+-                                 sensor_node->name,
+-                                 ep->bus.mipi_csi2.num_data_lanes,
+-                                 peripheral_data_lanes);
+-                      goto cleanup_exit;
+-              }
+-              for (lane = 0;
+-                   lane < ep->bus.mipi_csi2.num_data_lanes;
+-                   lane++) {
+-                      if (ep->bus.mipi_csi2.data_lanes[lane] != lane + 1) {
+-                              unicam_err(dev, "Subdevice %s - incompatible data lane config\n",
+-                                         sensor_node->name);
+-                              goto cleanup_exit;
+-                      }
+-              }
+-              dev->max_data_lanes = ep->bus.mipi_csi2.num_data_lanes;
+-              dev->bus_flags = ep->bus.mipi_csi2.flags;
+-              break;
+-      case V4L2_MBUS_CCP2:
+-              if (ep->bus.mipi_csi1.clock_lane != 0 ||
+-                  ep->bus.mipi_csi1.data_lane != 1) {
+-                      unicam_err(dev, "Subdevice %s incompatible lane config\n",
+-                                 sensor_node->name);
+-                      goto cleanup_exit;
+-              }
+-              dev->max_data_lanes = 1;
+-              dev->bus_flags = ep->bus.mipi_csi1.strobe;
+-              break;
+-      default:
+-              /* Unsupported bus type */
+-              unicam_err(dev, "sub-device %s is not a CSI2 or CCP2 device %d\n",
+-                         sensor_node->name, ep->bus_type);
+-              goto cleanup_exit;
+-      }
+-
+-      /* Store bus type - CSI2 or CCP2 */
+-      dev->bus_type = ep->bus_type;
+-      unicam_dbg(3, dev, "bus_type is %d\n", dev->bus_type);
+-
+-      /* Store Virtual Channel number */
+-      dev->virtual_channel = ep->base.id;
+-
+-      unicam_dbg(3, dev, "v4l2-endpoint: %s\n",
+-                 dev->bus_type == V4L2_MBUS_CSI2_DPHY ? "CSI2" : "CCP2");
+-      unicam_dbg(3, dev, "Virtual Channel=%d\n", dev->virtual_channel);
+-      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY)
+-              unicam_dbg(3, dev, "flags=0x%08x\n", ep->bus.mipi_csi2.flags);
+-      unicam_dbg(3, dev, "num_data_lanes=%d\n", dev->max_data_lanes);
+-
+-      unicam_dbg(1, dev, "found sub-device %s\n", sensor_node->name);
+-
+-      v4l2_async_notifier_init(&dev->notifier);
+-
+-      ret = v4l2_async_notifier_add_subdev(&dev->notifier, asd);
+-      if (ret) {
+-              unicam_err(dev, "Error adding subdevice - ret %d\n", ret);
+-              goto cleanup_exit;
+-      }
+-
+-      dev->notifier.ops = &unicam_async_ops;
+-      ret = v4l2_async_notifier_register(&dev->v4l2_dev,
+-                                         &dev->notifier);
+-      if (ret) {
+-              unicam_err(dev, "Error registering async notifier - ret %d\n",
+-                         ret);
+-              ret = -EINVAL;
+-      }
+-
+-cleanup_exit:
+-      if (remote_ep)
+-              of_node_put(remote_ep);
+-      if (sensor_node)
+-              of_node_put(sensor_node);
+-      if (ep_node)
+-              of_node_put(ep_node);
+-
+-      return ret;
+-}
+-
+-static int unicam_probe(struct platform_device *pdev)
+-{
+-      struct unicam_cfg *unicam_cfg;
+-      struct unicam_device *unicam;
+-      struct v4l2_ctrl_handler *hdl;
+-      struct resource *res;
+-      int ret;
+-
+-      unicam = devm_kzalloc(&pdev->dev, sizeof(*unicam), GFP_KERNEL);
+-      if (!unicam)
+-              return -ENOMEM;
+-
+-      unicam->pdev = pdev;
+-      unicam_cfg = &unicam->cfg;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      unicam_cfg->base = devm_ioremap_resource(&pdev->dev, res);
+-      if (IS_ERR(unicam_cfg->base)) {
+-              unicam_err(unicam, "Failed to get main io block\n");
+-              return PTR_ERR(unicam_cfg->base);
+-      }
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-      unicam_cfg->clk_gate_base = devm_ioremap_resource(&pdev->dev, res);
+-      if (IS_ERR(unicam_cfg->clk_gate_base)) {
+-              unicam_err(unicam, "Failed to get 2nd io block\n");
+-              return PTR_ERR(unicam_cfg->clk_gate_base);
+-      }
+-
+-      unicam->clock = devm_clk_get(&pdev->dev, "lp");
+-      if (IS_ERR(unicam->clock)) {
+-              unicam_err(unicam, "Failed to get clock\n");
+-              return PTR_ERR(unicam->clock);
+-      }
+-
+-      ret = platform_get_irq(pdev, 0);
+-      if (ret <= 0) {
+-              dev_err(&pdev->dev, "No IRQ resource\n");
+-              return -ENODEV;
+-      }
+-
+-      ret = devm_request_irq(&pdev->dev, ret, unicam_isr, 0,
+-                             "unicam_capture0", unicam);
+-      if (ret) {
+-              dev_err(&pdev->dev, "Unable to request interrupt\n");
+-              return -EINVAL;
+-      }
+-
+-      unicam->mdev.dev = &pdev->dev;
+-      strscpy(unicam->mdev.model, UNICAM_MODULE_NAME,
+-              sizeof(unicam->mdev.model));
+-      strscpy(unicam->mdev.serial, "", sizeof(unicam->mdev.serial));
+-      snprintf(unicam->mdev.bus_info, sizeof(unicam->mdev.bus_info),
+-               "platform:%s %s",
+-               pdev->dev.driver->name, dev_name(&pdev->dev));
+-      unicam->mdev.hw_revision = 1;
+-
+-      media_entity_pads_init(&unicam->node[IMAGE_PAD].video_dev.entity, 1,
+-                             &unicam->node[IMAGE_PAD].pad);
+-      media_entity_pads_init(&unicam->node[METADATA_PAD].video_dev.entity, 1,
+-                             &unicam->node[METADATA_PAD].pad);
+-      media_device_init(&unicam->mdev);
+-
+-      unicam->v4l2_dev.mdev = &unicam->mdev;
+-
+-      ret = v4l2_device_register(&pdev->dev, &unicam->v4l2_dev);
+-      if (ret) {
+-              unicam_err(unicam,
+-                         "Unable to register v4l2 device.\n");
+-              goto media_cleanup;
+-      }
+-
+-      ret = media_device_register(&unicam->mdev);
+-      if (ret < 0) {
+-              unicam_err(unicam,
+-                         "Unable to register media-controller device.\n");
+-              goto probe_out_v4l2_unregister;
+-      }
+-
+-      /* Reserve space for the controls */
+-      hdl = &unicam->node[IMAGE_PAD].ctrl_handler;
+-      ret = v4l2_ctrl_handler_init(hdl, 16);
+-      if (ret < 0)
+-              goto media_unregister;
+-
+-      /* set the driver data in platform device */
+-      platform_set_drvdata(pdev, unicam);
+-
+-      ret = of_unicam_connect_subdevs(unicam);
+-      if (ret) {
+-              dev_err(&pdev->dev, "Failed to connect subdevs\n");
+-              goto free_hdl;
+-      }
+-
+-      /* Enable the block power domain */
+-      pm_runtime_enable(&pdev->dev);
+-
+-      return 0;
+-
+-free_hdl:
+-      v4l2_ctrl_handler_free(hdl);
+-media_unregister:
+-      media_device_unregister(&unicam->mdev);
+-probe_out_v4l2_unregister:
+-      v4l2_device_unregister(&unicam->v4l2_dev);
+-media_cleanup:
+-      media_device_cleanup(&unicam->mdev);
+-
+-      return ret;
+-}
+-
+-static int unicam_remove(struct platform_device *pdev)
+-{
+-      struct unicam_device *unicam = platform_get_drvdata(pdev);
+-
+-      unicam_dbg(2, unicam, "%s\n", __func__);
+-
+-      pm_runtime_disable(&pdev->dev);
+-
+-      v4l2_async_notifier_unregister(&unicam->notifier);
+-      v4l2_ctrl_handler_free(&unicam->node[IMAGE_PAD].ctrl_handler);
+-      v4l2_device_unregister(&unicam->v4l2_dev);
+-      unregister_nodes(unicam);
+-      if (unicam->sensor_config)
+-              v4l2_subdev_free_pad_config(unicam->sensor_config);
+-      media_device_unregister(&unicam->mdev);
+-      media_device_cleanup(&unicam->mdev);
+-
+-      return 0;
+-}
+-
+-static const struct of_device_id unicam_of_match[] = {
+-      { .compatible = "brcm,bcm2835-unicam", },
+-      { /* sentinel */ },
+-};
+-MODULE_DEVICE_TABLE(of, unicam_of_match);
+-
+-static struct platform_driver unicam_driver = {
+-      .probe          = unicam_probe,
+-      .remove         = unicam_remove,
+-      .driver = {
+-              .name   = UNICAM_MODULE_NAME,
+-              .of_match_table = of_match_ptr(unicam_of_match),
+-      },
+-};
+-
+-module_platform_driver(unicam_driver);
+-
+-MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com>");
+-MODULE_DESCRIPTION("BCM2835 Unicam driver");
+-MODULE_LICENSE("GPL");
+-MODULE_VERSION(UNICAM_VERSION);
+--- a/drivers/media/platform/bcm2835/vc4-regs-unicam.h
++++ /dev/null
+@@ -1,253 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-only */
+-
+-/*
+- * Copyright (C) 2017-2020 Raspberry Pi Trading.
+- * Dave Stevenson <dave.stevenson@raspberrypi.com>
+- */
+-
+-#ifndef VC4_REGS_UNICAM_H
+-#define VC4_REGS_UNICAM_H
+-
+-/*
+- * The following values are taken from files found within the code drop
+- * made by Broadcom for the BCM21553 Graphics Driver, predominantly in
+- * brcm_usrlib/dag/vmcsx/vcinclude/hardware_vc4.h.
+- * They have been modified to be only the register offset.
+- */
+-#define UNICAM_CTRL   0x000
+-#define UNICAM_STA    0x004
+-#define UNICAM_ANA    0x008
+-#define UNICAM_PRI    0x00c
+-#define UNICAM_CLK    0x010
+-#define UNICAM_CLT    0x014
+-#define UNICAM_DAT0   0x018
+-#define UNICAM_DAT1   0x01c
+-#define UNICAM_DAT2   0x020
+-#define UNICAM_DAT3   0x024
+-#define UNICAM_DLT    0x028
+-#define UNICAM_CMP0   0x02c
+-#define UNICAM_CMP1   0x030
+-#define UNICAM_CAP0   0x034
+-#define UNICAM_CAP1   0x038
+-#define UNICAM_ICTL   0x100
+-#define UNICAM_ISTA   0x104
+-#define UNICAM_IDI0   0x108
+-#define UNICAM_IPIPE  0x10c
+-#define UNICAM_IBSA0  0x110
+-#define UNICAM_IBEA0  0x114
+-#define UNICAM_IBLS   0x118
+-#define UNICAM_IBWP   0x11c
+-#define UNICAM_IHWIN  0x120
+-#define UNICAM_IHSTA  0x124
+-#define UNICAM_IVWIN  0x128
+-#define UNICAM_IVSTA  0x12c
+-#define UNICAM_ICC    0x130
+-#define UNICAM_ICS    0x134
+-#define UNICAM_IDC    0x138
+-#define UNICAM_IDPO   0x13c
+-#define UNICAM_IDCA   0x140
+-#define UNICAM_IDCD   0x144
+-#define UNICAM_IDS    0x148
+-#define UNICAM_DCS    0x200
+-#define UNICAM_DBSA0  0x204
+-#define UNICAM_DBEA0  0x208
+-#define UNICAM_DBWP   0x20c
+-#define UNICAM_DBCTL  0x300
+-#define UNICAM_IBSA1  0x304
+-#define UNICAM_IBEA1  0x308
+-#define UNICAM_IDI1   0x30c
+-#define UNICAM_DBSA1  0x310
+-#define UNICAM_DBEA1  0x314
+-#define UNICAM_MISC   0x400
+-
+-/*
+- * The following bitmasks are from the kernel released by Broadcom
+- * for Android - https://android.googlesource.com/kernel/bcm/
+- * The Rhea, Hawaii, and Java chips all contain the same VideoCore4
+- * Unicam block as BCM2835, as defined in eg
+- * arch/arm/mach-rhea/include/mach/rdb_A0/brcm_rdb_cam.h and similar.
+- * Values reworked to use the kernel BIT and GENMASK macros.
+- *
+- * Some of the bit mnenomics have been amended to match the datasheet.
+- */
+-/* UNICAM_CTRL Register */
+-#define UNICAM_CPE            BIT(0)
+-#define UNICAM_MEM            BIT(1)
+-#define UNICAM_CPR            BIT(2)
+-#define UNICAM_CPM_MASK               GENMASK(3, 3)
+-#define UNICAM_CPM_CSI2               0
+-#define UNICAM_CPM_CCP2               1
+-#define UNICAM_SOE            BIT(4)
+-#define UNICAM_DCM_MASK               GENMASK(5, 5)
+-#define UNICAM_DCM_STROBE     0
+-#define UNICAM_DCM_DATA               1
+-#define UNICAM_SLS            BIT(6)
+-#define UNICAM_PFT_MASK               GENMASK(11, 8)
+-#define UNICAM_OET_MASK               GENMASK(20, 12)
+-
+-/* UNICAM_STA Register */
+-#define UNICAM_SYN            BIT(0)
+-#define UNICAM_CS             BIT(1)
+-#define UNICAM_SBE            BIT(2)
+-#define UNICAM_PBE            BIT(3)
+-#define UNICAM_HOE            BIT(4)
+-#define UNICAM_PLE            BIT(5)
+-#define UNICAM_SSC            BIT(6)
+-#define UNICAM_CRCE           BIT(7)
+-#define UNICAM_OES            BIT(8)
+-#define UNICAM_IFO            BIT(9)
+-#define UNICAM_OFO            BIT(10)
+-#define UNICAM_BFO            BIT(11)
+-#define UNICAM_DL             BIT(12)
+-#define UNICAM_PS             BIT(13)
+-#define UNICAM_IS             BIT(14)
+-#define UNICAM_PI0            BIT(15)
+-#define UNICAM_PI1            BIT(16)
+-#define UNICAM_FSI_S          BIT(17)
+-#define UNICAM_FEI_S          BIT(18)
+-#define UNICAM_LCI_S          BIT(19)
+-#define UNICAM_BUF0_RDY               BIT(20)
+-#define UNICAM_BUF0_NO                BIT(21)
+-#define UNICAM_BUF1_RDY               BIT(22)
+-#define UNICAM_BUF1_NO                BIT(23)
+-#define UNICAM_DI             BIT(24)
+-
+-#define UNICAM_STA_MASK_ALL \
+-              (UNICAM_DL + \
+-              UNICAM_SBE + \
+-              UNICAM_PBE + \
+-              UNICAM_HOE + \
+-              UNICAM_PLE + \
+-              UNICAM_SSC + \
+-              UNICAM_CRCE + \
+-              UNICAM_IFO + \
+-              UNICAM_OFO + \
+-              UNICAM_PS + \
+-              UNICAM_PI0 + \
+-              UNICAM_PI1)
+-
+-/* UNICAM_ANA Register */
+-#define UNICAM_APD            BIT(0)
+-#define UNICAM_BPD            BIT(1)
+-#define UNICAM_AR             BIT(2)
+-#define UNICAM_DDL            BIT(3)
+-#define UNICAM_CTATADJ_MASK   GENMASK(7, 4)
+-#define UNICAM_PTATADJ_MASK   GENMASK(11, 8)
+-
+-/* UNICAM_PRI Register */
+-#define UNICAM_PE             BIT(0)
+-#define UNICAM_PT_MASK                GENMASK(2, 1)
+-#define UNICAM_NP_MASK                GENMASK(7, 4)
+-#define UNICAM_PP_MASK                GENMASK(11, 8)
+-#define UNICAM_BS_MASK                GENMASK(15, 12)
+-#define UNICAM_BL_MASK                GENMASK(17, 16)
+-
+-/* UNICAM_CLK Register */
+-#define UNICAM_CLE            BIT(0)
+-#define UNICAM_CLPD           BIT(1)
+-#define UNICAM_CLLPE          BIT(2)
+-#define UNICAM_CLHSE          BIT(3)
+-#define UNICAM_CLTRE          BIT(4)
+-#define UNICAM_CLAC_MASK      GENMASK(8, 5)
+-#define UNICAM_CLSTE          BIT(29)
+-
+-/* UNICAM_CLT Register */
+-#define UNICAM_CLT1_MASK      GENMASK(7, 0)
+-#define UNICAM_CLT2_MASK      GENMASK(15, 8)
+-
+-/* UNICAM_DATn Registers */
+-#define UNICAM_DLE            BIT(0)
+-#define UNICAM_DLPD           BIT(1)
+-#define UNICAM_DLLPE          BIT(2)
+-#define UNICAM_DLHSE          BIT(3)
+-#define UNICAM_DLTRE          BIT(4)
+-#define UNICAM_DLSM           BIT(5)
+-#define UNICAM_DLFO           BIT(28)
+-#define UNICAM_DLSTE          BIT(29)
+-
+-#define UNICAM_DAT_MASK_ALL (UNICAM_DLSTE + UNICAM_DLFO)
+-
+-/* UNICAM_DLT Register */
+-#define UNICAM_DLT1_MASK      GENMASK(7, 0)
+-#define UNICAM_DLT2_MASK      GENMASK(15, 8)
+-#define UNICAM_DLT3_MASK      GENMASK(23, 16)
+-
+-/* UNICAM_ICTL Register */
+-#define UNICAM_FSIE           BIT(0)
+-#define UNICAM_FEIE           BIT(1)
+-#define UNICAM_IBOB           BIT(2)
+-#define UNICAM_FCM            BIT(3)
+-#define UNICAM_TFC            BIT(4)
+-#define UNICAM_LIP_MASK               GENMASK(6, 5)
+-#define UNICAM_LCIE_MASK      GENMASK(28, 16)
+-
+-/* UNICAM_IDI0/1 Register */
+-#define UNICAM_ID0_MASK               GENMASK(7, 0)
+-#define UNICAM_ID1_MASK               GENMASK(15, 8)
+-#define UNICAM_ID2_MASK               GENMASK(23, 16)
+-#define UNICAM_ID3_MASK               GENMASK(31, 24)
+-
+-/* UNICAM_ISTA Register */
+-#define UNICAM_FSI            BIT(0)
+-#define UNICAM_FEI            BIT(1)
+-#define UNICAM_LCI            BIT(2)
+-
+-#define UNICAM_ISTA_MASK_ALL (UNICAM_FSI + UNICAM_FEI + UNICAM_LCI)
+-
+-/* UNICAM_IPIPE Register */
+-#define UNICAM_PUM_MASK               GENMASK(2, 0)
+-              /* Unpacking modes */
+-              #define UNICAM_PUM_NONE         0
+-              #define UNICAM_PUM_UNPACK6      1
+-              #define UNICAM_PUM_UNPACK7      2
+-              #define UNICAM_PUM_UNPACK8      3
+-              #define UNICAM_PUM_UNPACK10     4
+-              #define UNICAM_PUM_UNPACK12     5
+-              #define UNICAM_PUM_UNPACK14     6
+-              #define UNICAM_PUM_UNPACK16     7
+-#define UNICAM_DDM_MASK               GENMASK(6, 3)
+-#define UNICAM_PPM_MASK               GENMASK(9, 7)
+-              /* Packing modes */
+-              #define UNICAM_PPM_NONE         0
+-              #define UNICAM_PPM_PACK8        1
+-              #define UNICAM_PPM_PACK10       2
+-              #define UNICAM_PPM_PACK12       3
+-              #define UNICAM_PPM_PACK14       4
+-              #define UNICAM_PPM_PACK16       5
+-#define UNICAM_DEM_MASK               GENMASK(11, 10)
+-#define UNICAM_DEBL_MASK      GENMASK(14, 12)
+-#define UNICAM_ICM_MASK               GENMASK(16, 15)
+-#define UNICAM_IDM_MASK               GENMASK(17, 17)
+-
+-/* UNICAM_ICC Register */
+-#define UNICAM_ICFL_MASK      GENMASK(4, 0)
+-#define UNICAM_ICFH_MASK      GENMASK(9, 5)
+-#define UNICAM_ICST_MASK      GENMASK(12, 10)
+-#define UNICAM_ICLT_MASK      GENMASK(15, 13)
+-#define UNICAM_ICLL_MASK      GENMASK(31, 16)
+-
+-/* UNICAM_DCS Register */
+-#define UNICAM_DIE            BIT(0)
+-#define UNICAM_DIM            BIT(1)
+-#define UNICAM_DBOB           BIT(3)
+-#define UNICAM_FDE            BIT(4)
+-#define UNICAM_LDP            BIT(5)
+-#define UNICAM_EDL_MASK               GENMASK(15, 8)
+-
+-/* UNICAM_DBCTL Register */
+-#define UNICAM_DBEN           BIT(0)
+-#define UNICAM_BUF0_IE                BIT(1)
+-#define UNICAM_BUF1_IE                BIT(2)
+-
+-/* UNICAM_CMP[0,1] register */
+-#define UNICAM_PCE            BIT(31)
+-#define UNICAM_GI             BIT(9)
+-#define UNICAM_CPH            BIT(8)
+-#define UNICAM_PCVC_MASK      GENMASK(7, 6)
+-#define UNICAM_PCDT_MASK      GENMASK(5, 0)
+-
+-/* UNICAM_MISC register */
+-#define UNICAM_FL0            BIT(6)
+-#define UNICAM_FL1            BIT(9)
+-
+-#endif
diff --git a/target/linux/bcm27xx/patches-5.4/950-0805-include-media-Add-vfl_devnode_type-of-VFL_TYPE_VIDEO.patch b/target/linux/bcm27xx/patches-5.4/950-0805-include-media-Add-vfl_devnode_type-of-VFL_TYPE_VIDEO.patch
new file mode 100644 (file)
index 0000000..acd3034
--- /dev/null
@@ -0,0 +1,25 @@
+From 7c74b86873fd5252becee33d092d8317ceff5f5b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 23 Jun 2020 10:35:24 +0100
+Subject: [PATCH] include: media: Add vfl_devnode_type of
+ VFL_TYPE_VIDEO
+
+Upsstream are renaming VFL_TYPE_GRABBER to VFL_TYPE_VIDEO.
+To make backporting the upstream Unicam driver easier, add an
+extra enum entry (same as VFL_TYPE_GRABBER) to match that.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ include/media/v4l2-dev.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/media/v4l2-dev.h
++++ b/include/media/v4l2-dev.h
+@@ -34,6 +34,7 @@
+  */
+ enum vfl_devnode_type {
+       VFL_TYPE_GRABBER        = 0,
++      VFL_TYPE_VIDEO = VFL_TYPE_GRABBER,
+       VFL_TYPE_VBI,
+       VFL_TYPE_RADIO,
+       VFL_TYPE_SUBDEV,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0806-media-bcm2835-unicam-Driver-for-CCP2-CSI2-camera-int.patch b/target/linux/bcm27xx/patches-5.4/950-0806-media-bcm2835-unicam-Driver-for-CCP2-CSI2-camera-int.patch
new file mode 100644 (file)
index 0000000..561b1fd
--- /dev/null
@@ -0,0 +1,3150 @@
+From c339b677f34884fdbe0e6bcdda6d59b7ae30d118 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Mon, 4 May 2020 12:25:41 +0300
+Subject: [PATCH] media: bcm2835-unicam: Driver for CCP2/CSI2 camera
+ interface
+
+Add a driver for the Unicam camera receiver block on BCM283x processors.
+Compared to the bcm2835-camera driver present in staging, this driver
+handles the Unicam block only (CSI-2 receiver), and doesn't depend on
+the VC4 firmware running on the VPU.
+
+The commit is made up of a series of changes cherry-picked from the
+rpi-5.4.y branch of https://github.com/raspberrypi/linux/ with
+additional enhancements, forward-ported to the mainline kernel.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reported-by: kbuild test robot <lkp@intel.com>
+---
+ MAINTAINERS                                   |    2 +-
+ drivers/media/platform/bcm2835/Kconfig        |   15 +
+ drivers/media/platform/bcm2835/Makefile       |    3 +
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 2825 +++++++++++++++++
+ .../media/platform/bcm2835/vc4-regs-unicam.h  |  253 ++
+ 5 files changed, 3097 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/media/platform/bcm2835/Kconfig
+ create mode 100644 drivers/media/platform/bcm2835/Makefile
+ create mode 100644 drivers/media/platform/bcm2835/bcm2835-unicam.c
+ create mode 100644 drivers/media/platform/bcm2835/vc4-regs-unicam.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3210,7 +3210,7 @@ M:       Raspberry Pi Kernel Maintenance <kern
+ L:    linux-media@vger.kernel.org
+ S:    Maintained
+ F:    drivers/media/platform/bcm2835/
+-F:    Documentation/devicetree/bindings/media/bcm2835-unicam.txt
++F:    Documentation/devicetree/bindings/media/brcm,bcm2835-unicam.yaml
+ BROADCOM BCM2835 ISP DRIVER
+ M:    Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
+--- /dev/null
++++ b/drivers/media/platform/bcm2835/Kconfig
+@@ -0,0 +1,15 @@
++# Broadcom VideoCore4 V4L2 camera support
++
++config VIDEO_BCM2835_UNICAM
++      tristate "Broadcom BCM2835 Unicam video capture driver"
++      depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
++      depends on ARCH_BCM2835 || COMPILE_TEST
++      select VIDEOBUF2_DMA_CONTIG
++      select V4L2_FWNODE
++      help
++        Say Y here to enable support for the BCM2835 CSI-2 receiver. This is a
++        V4L2 driver that controls the CSI-2 receiver directly, independently
++        from the VC4 firmware.
++
++        To compile this driver as a module, choose M here. The module will be
++        called bcm2835-unicam.
+--- /dev/null
++++ b/drivers/media/platform/bcm2835/Makefile
+@@ -0,0 +1,3 @@
++# Makefile for BCM2835 Unicam driver
++
++obj-$(CONFIG_VIDEO_BCM2835_UNICAM) += bcm2835-unicam.o
+--- /dev/null
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -0,0 +1,2825 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * BCM2835 Unicam Capture Driver
++ *
++ * Copyright (C) 2017-2020 - Raspberry Pi (Trading) Ltd.
++ *
++ * Dave Stevenson <dave.stevenson@raspberrypi.com>
++ *
++ * Based on TI am437x driver by
++ *   Benoit Parrot <bparrot@ti.com>
++ *   Lad, Prabhakar <prabhakar.csengg@gmail.com>
++ *
++ * and TI CAL camera interface driver by
++ *    Benoit Parrot <bparrot@ti.com>
++ *
++ *
++ * There are two camera drivers in the kernel for BCM283x - this one
++ * and bcm2835-camera (currently in staging).
++ *
++ * This driver directly controls the Unicam peripheral - there is no
++ * involvement with the VideoCore firmware. Unicam receives CSI-2 or
++ * CCP2 data and writes it into SDRAM.
++ * The only potential processing options are to repack Bayer data into an
++ * alternate format, and applying windowing.
++ * The repacking does not shift the data, so can repack V4L2_PIX_FMT_Sxxxx10P
++ * to V4L2_PIX_FMT_Sxxxx10, or V4L2_PIX_FMT_Sxxxx12P to V4L2_PIX_FMT_Sxxxx12,
++ * but not generically up to V4L2_PIX_FMT_Sxxxx16. The driver will add both
++ * formats where the relevant formats are defined, and will automatically
++ * configure the repacking as required.
++ * Support for windowing may be added later.
++ *
++ * It should be possible to connect this driver to any sensor with a
++ * suitable output interface and V4L2 subdevice driver.
++ *
++ * bcm2835-camera uses the VideoCore firmware to control the sensor,
++ * Unicam, ISP, and all tuner control loops. Fully processed frames are
++ * delivered to the driver by the firmware. It only has sensor drivers
++ * for Omnivision OV5647, and Sony IMX219 sensors.
++ *
++ * The two drivers are mutually exclusive for the same Unicam instance.
++ * The VideoCore firmware checks the device tree configuration during boot.
++ * If it finds device tree nodes called csi0 or csi1 it will block the
++ * firmware from accessing the peripheral, and bcm2835-camera will
++ * not be able to stream data.
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/of_graph.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++#include <linux/videodev2.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-dev.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-dv-timings.h>
++#include <media/v4l2-event.h>
++#include <media/v4l2-ioctl.h>
++#include <media/v4l2-fwnode.h>
++#include <media/videobuf2-dma-contig.h>
++
++#include "vc4-regs-unicam.h"
++
++#define UNICAM_MODULE_NAME    "unicam"
++#define UNICAM_VERSION                "0.1.0"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Debug level 0-3");
++
++#define unicam_dbg(level, dev, fmt, arg...)   \
++              v4l2_dbg(level, debug, &(dev)->v4l2_dev, fmt, ##arg)
++#define unicam_info(dev, fmt, arg...) \
++              v4l2_info(&(dev)->v4l2_dev, fmt, ##arg)
++#define unicam_err(dev, fmt, arg...)  \
++              v4l2_err(&(dev)->v4l2_dev, fmt, ##arg)
++
++/*
++ * To protect against a dodgy sensor driver never returning an error from
++ * enum_mbus_code, set a maximum index value to be used.
++ */
++#define MAX_ENUM_MBUS_CODE    128
++
++/*
++ * Stride is a 16 bit register, but also has to be a multiple of 32.
++ */
++#define BPL_ALIGNMENT         32
++#define MAX_BYTESPERLINE      ((1 << 16) - BPL_ALIGNMENT)
++/*
++ * Max width is therefore determined by the max stride divided by
++ * the number of bits per pixel. Take 32bpp as a
++ * worst case.
++ * No imposed limit on the height, so adopt a square image for want
++ * of anything better.
++ */
++#define MAX_WIDTH             (MAX_BYTESPERLINE / 4)
++#define MAX_HEIGHT            MAX_WIDTH
++/* Define a nominal minimum image size */
++#define MIN_WIDTH             16
++#define MIN_HEIGHT            16
++/* Default size of the embedded buffer */
++#define UNICAM_EMBEDDED_SIZE  8192
++
++/*
++ * Size of the dummy buffer. Can be any size really, but the DMA
++ * allocation works in units of page sizes.
++ */
++#define DUMMY_BUF_SIZE                (PAGE_SIZE)
++
++enum pad_types {
++      IMAGE_PAD,
++      METADATA_PAD,
++      MAX_NODES
++};
++
++/*
++ * struct unicam_fmt - Unicam media bus format information
++ * @pixelformat: V4L2 pixel format FCC identifier. 0 if n/a.
++ * @repacked_fourcc: V4L2 pixel format FCC identifier if the data is expanded
++ * out to 16bpp. 0 if n/a.
++ * @code: V4L2 media bus format code.
++ * @depth: Bits per pixel as delivered from the source.
++ * @csi_dt: CSI data type.
++ * @check_variants: Flag to denote that there are multiple mediabus formats
++ *            still in the list that could match this V4L2 format.
++ */
++struct unicam_fmt {
++      u32     fourcc;
++      u32     repacked_fourcc;
++      u32     code;
++      u8      depth;
++      u8      csi_dt;
++      u8      check_variants;
++};
++
++static const struct unicam_fmt formats[] = {
++      /* YUV Formats */
++      {
++              .fourcc         = V4L2_PIX_FMT_YUYV,
++              .code           = MEDIA_BUS_FMT_YUYV8_2X8,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++              .check_variants = 1,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_UYVY,
++              .code           = MEDIA_BUS_FMT_UYVY8_2X8,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++              .check_variants = 1,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_YVYU,
++              .code           = MEDIA_BUS_FMT_YVYU8_2X8,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++              .check_variants = 1,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_VYUY,
++              .code           = MEDIA_BUS_FMT_VYUY8_2X8,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++              .check_variants = 1,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_YUYV,
++              .code           = MEDIA_BUS_FMT_YUYV8_1X16,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_UYVY,
++              .code           = MEDIA_BUS_FMT_UYVY8_1X16,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_YVYU,
++              .code           = MEDIA_BUS_FMT_YVYU8_1X16,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_VYUY,
++              .code           = MEDIA_BUS_FMT_VYUY8_1X16,
++              .depth          = 16,
++              .csi_dt         = 0x1e,
++      }, {
++      /* RGB Formats */
++              .fourcc         = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
++              .code           = MEDIA_BUS_FMT_RGB565_2X8_LE,
++              .depth          = 16,
++              .csi_dt         = 0x22,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
++              .code           = MEDIA_BUS_FMT_RGB565_2X8_BE,
++              .depth          = 16,
++              .csi_dt         = 0x22
++      }, {
++              .fourcc         = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
++              .code           = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
++              .depth          = 16,
++              .csi_dt         = 0x21,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
++              .code           = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
++              .depth          = 16,
++              .csi_dt         = 0x21,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_RGB24, /* rgb */
++              .code           = MEDIA_BUS_FMT_RGB888_1X24,
++              .depth          = 24,
++              .csi_dt         = 0x24,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_BGR24, /* bgr */
++              .code           = MEDIA_BUS_FMT_BGR888_1X24,
++              .depth          = 24,
++              .csi_dt         = 0x24,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_RGB32, /* argb */
++              .code           = MEDIA_BUS_FMT_ARGB8888_1X32,
++              .depth          = 32,
++              .csi_dt         = 0x0,
++      }, {
++      /* Bayer Formats */
++              .fourcc         = V4L2_PIX_FMT_SBGGR8,
++              .code           = MEDIA_BUS_FMT_SBGGR8_1X8,
++              .depth          = 8,
++              .csi_dt         = 0x2a,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGBRG8,
++              .code           = MEDIA_BUS_FMT_SGBRG8_1X8,
++              .depth          = 8,
++              .csi_dt         = 0x2a,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGRBG8,
++              .code           = MEDIA_BUS_FMT_SGRBG8_1X8,
++              .depth          = 8,
++              .csi_dt         = 0x2a,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SRGGB8,
++              .code           = MEDIA_BUS_FMT_SRGGB8_1X8,
++              .depth          = 8,
++              .csi_dt         = 0x2a,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SBGGR10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SBGGR10,
++              .code           = MEDIA_BUS_FMT_SBGGR10_1X10,
++              .depth          = 10,
++              .csi_dt         = 0x2b,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGBRG10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGBRG10,
++              .code           = MEDIA_BUS_FMT_SGBRG10_1X10,
++              .depth          = 10,
++              .csi_dt         = 0x2b,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGRBG10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGRBG10,
++              .code           = MEDIA_BUS_FMT_SGRBG10_1X10,
++              .depth          = 10,
++              .csi_dt         = 0x2b,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SRGGB10P,
++              .repacked_fourcc = V4L2_PIX_FMT_SRGGB10,
++              .code           = MEDIA_BUS_FMT_SRGGB10_1X10,
++              .depth          = 10,
++              .csi_dt         = 0x2b,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SBGGR12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SBGGR12,
++              .code           = MEDIA_BUS_FMT_SBGGR12_1X12,
++              .depth          = 12,
++              .csi_dt         = 0x2c,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGBRG12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGBRG12,
++              .code           = MEDIA_BUS_FMT_SGBRG12_1X12,
++              .depth          = 12,
++              .csi_dt         = 0x2c,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGRBG12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGRBG12,
++              .code           = MEDIA_BUS_FMT_SGRBG12_1X12,
++              .depth          = 12,
++              .csi_dt         = 0x2c,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SRGGB12P,
++              .repacked_fourcc = V4L2_PIX_FMT_SRGGB12,
++              .code           = MEDIA_BUS_FMT_SRGGB12_1X12,
++              .depth          = 12,
++              .csi_dt         = 0x2c,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SBGGR14P,
++              .code           = MEDIA_BUS_FMT_SBGGR14_1X14,
++              .depth          = 14,
++              .csi_dt         = 0x2d,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGBRG14P,
++              .code           = MEDIA_BUS_FMT_SGBRG14_1X14,
++              .depth          = 14,
++              .csi_dt         = 0x2d,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SGRBG14P,
++              .code           = MEDIA_BUS_FMT_SGRBG14_1X14,
++              .depth          = 14,
++              .csi_dt         = 0x2d,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_SRGGB14P,
++              .code           = MEDIA_BUS_FMT_SRGGB14_1X14,
++              .depth          = 14,
++              .csi_dt         = 0x2d,
++      }, {
++      /*
++       * 16 bit Bayer formats could be supported, but there is no CSI2
++       * data_type defined for raw 16, and no sensors that produce it at
++       * present.
++       */
++
++      /* Greyscale formats */
++              .fourcc         = V4L2_PIX_FMT_GREY,
++              .code           = MEDIA_BUS_FMT_Y8_1X8,
++              .depth          = 8,
++              .csi_dt         = 0x2a,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_Y10P,
++              .repacked_fourcc = V4L2_PIX_FMT_Y10,
++              .code           = MEDIA_BUS_FMT_Y10_1X10,
++              .depth          = 10,
++              .csi_dt         = 0x2b,
++      }, {
++              /* NB There is no packed V4L2 fourcc for this format. */
++              .repacked_fourcc = V4L2_PIX_FMT_Y12,
++              .code           = MEDIA_BUS_FMT_Y12_1X12,
++              .depth          = 12,
++              .csi_dt         = 0x2c,
++      },
++      /* Embedded data format */
++      {
++              .fourcc         = V4L2_META_FMT_SENSOR_DATA,
++              .code           = MEDIA_BUS_FMT_SENSOR_DATA,
++              .depth          = 8,
++      }
++};
++
++struct unicam_buffer {
++      struct vb2_v4l2_buffer vb;
++      struct list_head list;
++};
++
++static inline struct unicam_buffer *to_unicam_buffer(struct vb2_buffer *vb)
++{
++      return container_of(vb, struct unicam_buffer, vb.vb2_buf);
++}
++
++struct unicam_node {
++      bool registered;
++      int open;
++      bool streaming;
++      unsigned int pad_id;
++      /* Pointer pointing to current v4l2_buffer */
++      struct unicam_buffer *cur_frm;
++      /* Pointer pointing to next v4l2_buffer */
++      struct unicam_buffer *next_frm;
++      /* video capture */
++      const struct unicam_fmt *fmt;
++      /* Used to store current pixel format */
++      struct v4l2_format v_fmt;
++      /* Used to store current mbus frame format */
++      struct v4l2_mbus_framefmt m_fmt;
++      /* Buffer queue used in video-buf */
++      struct vb2_queue buffer_queue;
++      /* Queue of filled frames */
++      struct list_head dma_queue;
++      /* IRQ lock for DMA queue */
++      spinlock_t dma_queue_lock;
++      /* lock used to access this structure */
++      struct mutex lock;
++      /* Identifies video device for this channel */
++      struct video_device video_dev;
++      /* Pointer to the parent handle */
++      struct unicam_device *dev;
++      struct media_pad pad;
++      unsigned int embedded_lines;
++      /*
++       * Dummy buffer intended to be used by unicam
++       * if we have no other queued buffers to swap to.
++       */
++      void *dummy_buf_cpu_addr;
++      dma_addr_t dummy_buf_dma_addr;
++};
++
++struct unicam_device {
++      struct kref kref;
++
++      /* V4l2 specific parameters */
++      struct v4l2_async_subdev asd;
++
++      /* peripheral base address */
++      void __iomem *base;
++      /* clock gating base address */
++      void __iomem *clk_gate_base;
++      /* clock handle */
++      struct clk *clock;
++      /* V4l2 device */
++      struct v4l2_device v4l2_dev;
++      struct media_device mdev;
++
++      /* parent device */
++      struct platform_device *pdev;
++      /* subdevice async Notifier */
++      struct v4l2_async_notifier notifier;
++      unsigned int sequence;
++
++      /* ptr to  sub device */
++      struct v4l2_subdev *sensor;
++      /* Pad config for the sensor */
++      struct v4l2_subdev_pad_config *sensor_config;
++
++      enum v4l2_mbus_type bus_type;
++      /*
++       * Stores bus.mipi_csi2.flags for CSI2 sensors, or
++       * bus.mipi_csi1.strobe for CCP2.
++       */
++      unsigned int bus_flags;
++      unsigned int max_data_lanes;
++      unsigned int active_data_lanes;
++      bool sensor_embedded_data;
++
++      struct unicam_node node[MAX_NODES];
++      struct v4l2_ctrl_handler ctrl_handler;
++};
++
++static inline struct unicam_device *
++to_unicam_device(struct v4l2_device *v4l2_dev)
++{
++      return container_of(v4l2_dev, struct unicam_device, v4l2_dev);
++}
++
++/* Hardware access */
++static inline void clk_write(struct unicam_device *dev, u32 val)
++{
++      writel(val | 0x5a000000, dev->clk_gate_base);
++}
++
++static inline u32 reg_read(struct unicam_device *dev, u32 offset)
++{
++      return readl(dev->base + offset);
++}
++
++static inline void reg_write(struct unicam_device *dev, u32 offset, u32 val)
++{
++      writel(val, dev->base + offset);
++}
++
++static inline int get_field(u32 value, u32 mask)
++{
++      return (value & mask) >> __ffs(mask);
++}
++
++static inline void set_field(u32 *valp, u32 field, u32 mask)
++{
++      u32 val = *valp;
++
++      val &= ~mask;
++      val |= (field << __ffs(mask)) & mask;
++      *valp = val;
++}
++
++static inline u32 reg_read_field(struct unicam_device *dev, u32 offset,
++                               u32 mask)
++{
++      return get_field(reg_read(dev, offset), mask);
++}
++
++static inline void reg_write_field(struct unicam_device *dev, u32 offset,
++                                 u32 field, u32 mask)
++{
++      u32 val = reg_read(dev, offset);
++
++      set_field(&val, field, mask);
++      reg_write(dev, offset, val);
++}
++
++/* Power management functions */
++static inline int unicam_runtime_get(struct unicam_device *dev)
++{
++      return pm_runtime_get_sync(&dev->pdev->dev);
++}
++
++static inline void unicam_runtime_put(struct unicam_device *dev)
++{
++      pm_runtime_put_sync(&dev->pdev->dev);
++}
++
++/* Format setup functions */
++static const struct unicam_fmt *find_format_by_code(u32 code)
++{
++      unsigned int i;
++
++      for (i = 0; i < ARRAY_SIZE(formats); i++) {
++              if (formats[i].code == code)
++                      return &formats[i];
++      }
++
++      return NULL;
++}
++
++static int check_mbus_format(struct unicam_device *dev,
++                           const struct unicam_fmt *format)
++{
++      unsigned int i;
++      int ret = 0;
++
++      for (i = 0; !ret && i < MAX_ENUM_MBUS_CODE; i++) {
++              struct v4l2_subdev_mbus_code_enum mbus_code = {
++                      .index = i,
++                      .pad = IMAGE_PAD,
++                      .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++              };
++
++              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code,
++                                     NULL, &mbus_code);
++
++              if (!ret && mbus_code.code == format->code)
++                      return 1;
++      }
++
++      return 0;
++}
++
++static const struct unicam_fmt *find_format_by_pix(struct unicam_device *dev,
++                                                 u32 pixelformat)
++{
++      unsigned int i;
++
++      for (i = 0; i < ARRAY_SIZE(formats); i++) {
++              if (formats[i].fourcc == pixelformat ||
++                  formats[i].repacked_fourcc == pixelformat) {
++                      if (formats[i].check_variants &&
++                          !check_mbus_format(dev, &formats[i]))
++                              continue;
++                      return &formats[i];
++              }
++      }
++
++      return NULL;
++}
++
++static inline unsigned int bytes_per_line(u32 width,
++                                        const struct unicam_fmt *fmt,
++                                        u32 v4l2_fourcc)
++{
++      if (v4l2_fourcc == fmt->repacked_fourcc)
++              /* Repacking always goes to 16bpp */
++              return ALIGN(width << 1, BPL_ALIGNMENT);
++      else
++              return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
++}
++
++static int __subdev_get_format(struct unicam_device *dev,
++                             struct v4l2_mbus_framefmt *fmt, int pad_id)
++{
++      struct v4l2_subdev_format sd_fmt = {
++              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++              .pad = pad_id
++      };
++      int ret;
++
++      ret = v4l2_subdev_call(dev->sensor, pad, get_fmt, dev->sensor_config,
++                             &sd_fmt);
++      if (ret < 0)
++              return ret;
++
++      *fmt = sd_fmt.format;
++
++      unicam_dbg(1, dev, "%s %dx%d code:%04x\n", __func__,
++                 fmt->width, fmt->height, fmt->code);
++
++      return 0;
++}
++
++static int __subdev_set_format(struct unicam_device *dev,
++                             struct v4l2_mbus_framefmt *fmt, int pad_id)
++{
++      struct v4l2_subdev_format sd_fmt = {
++              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++              .pad = pad_id
++      };
++      int ret;
++
++      sd_fmt.format = *fmt;
++
++      ret = v4l2_subdev_call(dev->sensor, pad, set_fmt, dev->sensor_config,
++                             &sd_fmt);
++      if (ret < 0)
++              return ret;
++
++      *fmt = sd_fmt.format;
++
++      if (pad_id == IMAGE_PAD)
++              unicam_dbg(1, dev, "%s %dx%d code:%04x\n", __func__, fmt->width,
++                         fmt->height, fmt->code);
++      else
++              unicam_dbg(1, dev, "%s Embedded data code:%04x\n", __func__,
++                         sd_fmt.format.code);
++
++      return 0;
++}
++
++static int unicam_calc_format_size_bpl(struct unicam_device *dev,
++                                     const struct unicam_fmt *fmt,
++                                     struct v4l2_format *f)
++{
++      unsigned int min_bytesperline;
++
++      v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 2,
++                            &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0,
++                            0);
++
++      min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt,
++                                        f->fmt.pix.pixelformat);
++
++      if (f->fmt.pix.bytesperline > min_bytesperline &&
++          f->fmt.pix.bytesperline <= MAX_BYTESPERLINE)
++              f->fmt.pix.bytesperline = ALIGN(f->fmt.pix.bytesperline,
++                                              BPL_ALIGNMENT);
++      else
++              f->fmt.pix.bytesperline = min_bytesperline;
++
++      f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
++
++      unicam_dbg(3, dev, "%s: fourcc: %08X size: %dx%d bpl:%d img_size:%d\n",
++                 __func__,
++                 f->fmt.pix.pixelformat,
++                 f->fmt.pix.width, f->fmt.pix.height,
++                 f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
++
++      return 0;
++}
++
++static int unicam_reset_format(struct unicam_node *node)
++{
++      struct unicam_device *dev = node->dev;
++      struct v4l2_mbus_framefmt mbus_fmt;
++      int ret;
++
++      if (dev->sensor_embedded_data || node->pad_id != METADATA_PAD) {
++              ret = __subdev_get_format(dev, &mbus_fmt, node->pad_id);
++              if (ret) {
++                      unicam_err(dev, "Failed to get_format - ret %d\n", ret);
++                      return ret;
++              }
++
++              if (mbus_fmt.code != node->fmt->code) {
++                      unicam_err(dev, "code mismatch - fmt->code %08x, mbus_fmt.code %08x\n",
++                                 node->fmt->code, mbus_fmt.code);
++                      return ret;
++              }
++      }
++
++      if (node->pad_id == IMAGE_PAD) {
++              v4l2_fill_pix_format(&node->v_fmt.fmt.pix, &mbus_fmt);
++              node->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++              unicam_calc_format_size_bpl(dev, node->fmt, &node->v_fmt);
++      } else {
++              node->v_fmt.type = V4L2_BUF_TYPE_META_CAPTURE;
++              node->v_fmt.fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA;
++              if (dev->sensor_embedded_data) {
++                      node->v_fmt.fmt.meta.buffersize =
++                                      mbus_fmt.width * mbus_fmt.height;
++                      node->embedded_lines = mbus_fmt.height;
++              } else {
++                      node->v_fmt.fmt.meta.buffersize = UNICAM_EMBEDDED_SIZE;
++                      node->embedded_lines = 1;
++              }
++      }
++
++      node->m_fmt = mbus_fmt;
++      return 0;
++}
++
++static void unicam_wr_dma_addr(struct unicam_device *dev, dma_addr_t dmaaddr,
++                             unsigned int buffer_size, int pad_id)
++{
++      dma_addr_t endaddr = dmaaddr + buffer_size;
++
++      /*
++       * dmaaddr and endaddr should be a 32-bit address with the top two bits
++       * set to 0x3 to signify uncached access through the Videocore memory
++       * controller.
++       */
++      WARN_ON((dmaaddr >> 30) != 0x3 || (endaddr >> 30) != 0x3);
++
++      if (pad_id == IMAGE_PAD) {
++              reg_write(dev, UNICAM_IBSA0, dmaaddr);
++              reg_write(dev, UNICAM_IBEA0, endaddr);
++      } else {
++              reg_write(dev, UNICAM_DBSA0, dmaaddr);
++              reg_write(dev, UNICAM_DBEA0, endaddr);
++      }
++}
++
++static inline unsigned int unicam_get_lines_done(struct unicam_device *dev)
++{
++      dma_addr_t start_addr, cur_addr;
++      unsigned int stride = dev->node[IMAGE_PAD].v_fmt.fmt.pix.bytesperline;
++      struct unicam_buffer *frm = dev->node[IMAGE_PAD].cur_frm;
++
++      if (!frm)
++              return 0;
++
++      start_addr = vb2_dma_contig_plane_dma_addr(&frm->vb.vb2_buf, 0);
++      cur_addr = reg_read(dev, UNICAM_IBWP);
++      return (unsigned int)(cur_addr - start_addr) / stride;
++}
++
++static inline void unicam_schedule_next_buffer(struct unicam_node *node)
++{
++      struct unicam_device *dev = node->dev;
++      struct unicam_buffer *buf;
++      unsigned int size;
++      dma_addr_t addr;
++
++      buf = list_first_entry(&node->dma_queue, struct unicam_buffer, list);
++      node->next_frm = buf;
++      list_del(&buf->list);
++
++      addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
++      size = (node->pad_id == IMAGE_PAD) ?
++                      node->v_fmt.fmt.pix.sizeimage :
++                      node->v_fmt.fmt.meta.buffersize;
++
++      unicam_wr_dma_addr(dev, addr, size, node->pad_id);
++}
++
++static inline void unicam_schedule_dummy_buffer(struct unicam_node *node)
++{
++      struct unicam_device *dev = node->dev;
++
++      unicam_dbg(3, dev, "Scheduling dummy buffer for node %d\n",
++                 node->pad_id);
++
++      unicam_wr_dma_addr(dev, node->dummy_buf_dma_addr, DUMMY_BUF_SIZE,
++                         node->pad_id);
++      node->next_frm = NULL;
++}
++
++static inline void unicam_process_buffer_complete(struct unicam_node *node,
++                                                unsigned int sequence)
++{
++      node->cur_frm->vb.field = node->m_fmt.field;
++      node->cur_frm->vb.sequence = sequence;
++
++      vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
++}
++
++static bool unicam_all_nodes_streaming(struct unicam_device *dev)
++{
++      bool ret;
++
++      ret = dev->node[IMAGE_PAD].open && dev->node[IMAGE_PAD].streaming;
++      ret &= !dev->node[METADATA_PAD].open ||
++             dev->node[METADATA_PAD].streaming;
++      return ret;
++}
++
++static bool unicam_all_nodes_disabled(struct unicam_device *dev)
++{
++      return !dev->node[IMAGE_PAD].streaming &&
++             !dev->node[METADATA_PAD].streaming;
++}
++
++static void unicam_queue_event_sof(struct unicam_device *unicam)
++{
++      struct v4l2_event event = {
++              .type = V4L2_EVENT_FRAME_SYNC,
++              .u.frame_sync.frame_sequence = unicam->sequence,
++      };
++
++      v4l2_event_queue(&unicam->node[IMAGE_PAD].video_dev, &event);
++}
++
++/*
++ * unicam_isr : ISR handler for unicam capture
++ * @irq: irq number
++ * @dev_id: dev_id ptr
++ *
++ * It changes status of the captured buffer, takes next buffer from the queue
++ * and sets its address in unicam registers
++ */
++static irqreturn_t unicam_isr(int irq, void *dev)
++{
++      struct unicam_device *unicam = dev;
++      unsigned int lines_done = unicam_get_lines_done(dev);
++      unsigned int sequence = unicam->sequence;
++      unsigned int i;
++      u32 ista, sta;
++      u64 ts;
++
++      /*
++       * Don't service interrupts if not streaming.
++       * Avoids issues if the VPU should enable the
++       * peripheral without the kernel knowing (that
++       * shouldn't happen, but causes issues if it does).
++       */
++      if (unicam_all_nodes_disabled(unicam))
++              return IRQ_NONE;
++
++      sta = reg_read(unicam, UNICAM_STA);
++      /* Write value back to clear the interrupts */
++      reg_write(unicam, UNICAM_STA, sta);
++
++      ista = reg_read(unicam, UNICAM_ISTA);
++      /* Write value back to clear the interrupts */
++      reg_write(unicam, UNICAM_ISTA, ista);
++
++      unicam_dbg(3, unicam, "ISR: ISTA: 0x%X, STA: 0x%X, sequence %d, lines done %d",
++                 ista, sta, sequence, lines_done);
++
++      if (!(sta & (UNICAM_IS | UNICAM_PI0)))
++              return IRQ_HANDLED;
++
++      /*
++       * We must run the frame end handler first. If we have a valid next_frm
++       * and we get a simultaneout FE + FS interrupt, running the FS handler
++       * first would null out the next_frm ptr and we would have lost the
++       * buffer forever.
++       */
++      if (ista & UNICAM_FEI || sta & UNICAM_PI0) {
++              /*
++               * Ensure we have swapped buffers already as we can't
++               * stop the peripheral. If no buffer is available, use a
++               * dummy buffer to dump out frames until we get a new buffer
++               * to use.
++               */
++              for (i = 0; i < ARRAY_SIZE(unicam->node); i++) {
++                      if (!unicam->node[i].streaming)
++                              continue;
++
++                      if (unicam->node[i].cur_frm)
++                              unicam_process_buffer_complete(&unicam->node[i],
++                                                             sequence);
++                      unicam->node[i].cur_frm = unicam->node[i].next_frm;
++              }
++              unicam->sequence++;
++      }
++
++      if (ista & UNICAM_FSI) {
++              /*
++               * Timestamp is to be when the first data byte was captured,
++               * aka frame start.
++               */
++              ts = ktime_get_ns();
++              for (i = 0; i < ARRAY_SIZE(unicam->node); i++) {
++                      if (!unicam->node[i].streaming)
++                              continue;
++
++                      if (unicam->node[i].cur_frm)
++                              unicam->node[i].cur_frm->vb.vb2_buf.timestamp =
++                                                              ts;
++                      /*
++                       * Set the next frame output to go to a dummy frame
++                       * if we have not managed to obtain another frame
++                       * from the queue.
++                       */
++                      unicam_schedule_dummy_buffer(&unicam->node[i]);
++              }
++
++              unicam_queue_event_sof(unicam);
++      }
++
++      /*
++       * Cannot swap buffer at frame end, there may be a race condition
++       * where the HW does not actually swap it if the new frame has
++       * already started.
++       */
++      if (ista & (UNICAM_FSI | UNICAM_LCI) && !(ista & UNICAM_FEI)) {
++              for (i = 0; i < ARRAY_SIZE(unicam->node); i++) {
++                      if (!unicam->node[i].streaming)
++                              continue;
++
++                      spin_lock(&unicam->node[i].dma_queue_lock);
++                      if (!list_empty(&unicam->node[i].dma_queue) &&
++                          !unicam->node[i].next_frm)
++                              unicam_schedule_next_buffer(&unicam->node[i]);
++                      spin_unlock(&unicam->node[i].dma_queue_lock);
++              }
++      }
++
++      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;
++}
++
++static int unicam_querycap(struct file *file, void *priv,
++                         struct v4l2_capability *cap)
++{
++      struct unicam_node *node = video_drvdata(file);
++      struct unicam_device *dev = node->dev;
++
++      strlcpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
++      strlcpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
++
++      snprintf(cap->bus_info, sizeof(cap->bus_info),
++               "platform:%s", dev_name(&dev->pdev->dev));
++
++      cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE;
++
++      return 0;
++}
++
++static int unicam_enum_fmt_vid_cap(struct file *file, void  *priv,
++                                 struct v4l2_fmtdesc *f)
++{
++      struct unicam_node *node = video_drvdata(file);
++      struct unicam_device *dev = node->dev;
++      unsigned int index = 0;
++      unsigned int i;
++      int ret = 0;
++
++      if (node->pad_id != IMAGE_PAD)
++              return -EINVAL;
++
++      for (i = 0; !ret && i < MAX_ENUM_MBUS_CODE; i++) {
++              struct v4l2_subdev_mbus_code_enum mbus_code = {
++                      .index = i,
++                      .pad = IMAGE_PAD,
++                      .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++              };
++              const struct unicam_fmt *fmt;
++
++              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code,
++                                     NULL, &mbus_code);
++              if (ret < 0) {
++                      unicam_dbg(2, dev,
++                                 "subdev->enum_mbus_code idx %d returned %d - index invalid\n",
++                                 i, ret);
++                      return -EINVAL;
++              }
++
++              fmt = find_format_by_code(mbus_code.code);
++              if (fmt) {
++                      if (fmt->fourcc) {
++                              if (index == f->index) {
++                                      f->pixelformat = fmt->fourcc;
++                                      break;
++                              }
++                              index++;
++                      }
++                      if (fmt->repacked_fourcc) {
++                              if (index == f->index) {
++                                      f->pixelformat = fmt->repacked_fourcc;
++                                      break;
++                              }
++                              index++;
++                      }
++              }
++      }
++
++      return 0;
++}
++
++static int unicam_g_fmt_vid_cap(struct file *file, void *priv,
++                              struct v4l2_format *f)
++{
++      struct v4l2_mbus_framefmt mbus_fmt = {0};
++      struct unicam_node *node = video_drvdata(file);
++      struct unicam_device *dev = node->dev;
++      const struct unicam_fmt *fmt = NULL;
++      int ret;
++
++      if (node->pad_id != IMAGE_PAD)
++              return -EINVAL;
++
++      /*
++       * If a flip has occurred in the sensor, the fmt code might have
++       * changed. So we will need to re-fetch the format from the subdevice.
++       */
++      ret = __subdev_get_format(dev, &mbus_fmt, node->pad_id);
++      if (ret)
++              return -EINVAL;
++
++      /* Find the V4L2 format from mbus code. We must match a known format. */
++      fmt = find_format_by_code(mbus_fmt.code);
++      if (!fmt)
++              return -EINVAL;
++
++      node->fmt = fmt;
++      node->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++      *f = node->v_fmt;
++
++      return 0;
++}
++
++static
++const struct unicam_fmt *get_first_supported_format(struct unicam_device *dev)
++{
++      struct v4l2_subdev_mbus_code_enum mbus_code;
++      const struct unicam_fmt *fmt = NULL;
++      unsigned int i;
++      int ret;
++
++      for (i = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++i) {
++              memset(&mbus_code, 0, sizeof(mbus_code));
++              mbus_code.index = i;
++              mbus_code.pad = IMAGE_PAD;
++              mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
++
++              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code, NULL,
++                                     &mbus_code);
++              if (ret < 0) {
++                      unicam_dbg(2, dev,
++                                 "subdev->enum_mbus_code idx %u returned %d - continue\n",
++                                 i, ret);
++                      continue;
++              }
++
++              unicam_dbg(2, dev, "subdev %s: code: 0x%08x idx: %u\n",
++                         dev->sensor->name, mbus_code.code, i);
++
++              fmt = find_format_by_code(mbus_code.code);
++              unicam_dbg(2, dev, "fmt 0x%08x returned as %p, V4L2 FOURCC 0x%08x, csi_dt 0x%02x\n",
++                         mbus_code.code, fmt, fmt ? fmt->fourcc : 0,
++                         fmt ? fmt->csi_dt : 0);
++              if (fmt)
++                      return fmt;
++      }
++
++      return NULL;
++}
++
++static int unicam_try_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;
++      struct v4l2_subdev_format sd_fmt = {
++              .which = V4L2_SUBDEV_FORMAT_TRY,
++              .pad = IMAGE_PAD
++      };
++      struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
++      const struct unicam_fmt *fmt;
++      int ret;
++
++      if (node->pad_id != IMAGE_PAD)
++              return -EINVAL;
++
++      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
++      if (!fmt) {
++              /*
++               * Pixel format not supported by unicam. Choose the first
++               * supported format, and let the sensor choose something else.
++               */
++              unicam_dbg(3, dev, "Fourcc format (0x%08x) not found. Use first format.\n",
++                         f->fmt.pix.pixelformat);
++
++              fmt = &formats[0];
++              f->fmt.pix.pixelformat = fmt->fourcc;
++      }
++
++      v4l2_fill_mbus_format(mbus_fmt, &f->fmt.pix, fmt->code);
++      /*
++       * No support for receiving interlaced video, so never
++       * request it from the sensor subdev.
++       */
++      mbus_fmt->field = V4L2_FIELD_NONE;
++
++      ret = v4l2_subdev_call(dev->sensor, pad, set_fmt, dev->sensor_config,
++                             &sd_fmt);
++      if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
++              return ret;
++
++      if (mbus_fmt->field != V4L2_FIELD_NONE)
++              unicam_info(dev, "Sensor trying to send interlaced video - results may be unpredictable\n");
++
++      v4l2_fill_pix_format(&f->fmt.pix, &sd_fmt.format);
++      if (mbus_fmt->code != fmt->code) {
++              /* Sensor has returned an alternate format */
++              fmt = find_format_by_code(mbus_fmt->code);
++              if (!fmt) {
++                      /*
++                       * The alternate format is one unicam can't support.
++                       * Find the first format that is supported by both, and
++                       * then set that.
++                       */
++                      fmt = get_first_supported_format(dev);
++                      mbus_fmt->code = fmt->code;
++
++                      ret = v4l2_subdev_call(dev->sensor, pad, set_fmt,
++                                             dev->sensor_config, &sd_fmt);
++                      if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
++                              return ret;
++
++                      if (mbus_fmt->field != V4L2_FIELD_NONE)
++                              unicam_info(dev, "Sensor trying to send interlaced video - results may be unpredictable\n");
++
++                      v4l2_fill_pix_format(&f->fmt.pix, &sd_fmt.format);
++
++                      if (mbus_fmt->code != fmt->code) {
++                              /*
++                               * We've set a format that the sensor reports
++                               * as being supported, but it refuses to set it.
++                               * Not much else we can do.
++                               * Assume that the sensor driver may accept the
++                               * format when it is set (rather than tried).
++                               */
++                              unicam_err(dev, "Sensor won't accept default format, and Unicam can't support sensor default\n");
++                      }
++              }
++
++              if (fmt->fourcc)
++                      f->fmt.pix.pixelformat = fmt->fourcc;
++              else
++                      f->fmt.pix.pixelformat = fmt->repacked_fourcc;
++      }
++
++      return unicam_calc_format_size_bpl(dev, fmt, f);
++}
++
++static int unicam_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;
++      struct vb2_queue *q = &node->buffer_queue;
++      struct v4l2_mbus_framefmt mbus_fmt = {0};
++      const struct unicam_fmt *fmt;
++      int ret;
++
++      if (vb2_is_busy(q))
++              return -EBUSY;
++
++      ret = unicam_try_fmt_vid_cap(file, priv, f);
++      if (ret < 0)
++              return ret;
++
++      fmt = find_format_by_pix(dev, f->fmt.pix.pixelformat);
++      if (!fmt) {
++              /*
++               * Unknown pixel format - adopt a default.
++               * This shouldn't happen as try_fmt should have resolved any
++               * issues first.
++               */
++              fmt = get_first_supported_format(dev);
++              if (!fmt)
++                      /*
++                       * It shouldn't be possible to get here with no
++                       * supported formats
++                       */
++                      return -EINVAL;
++              f->fmt.pix.pixelformat = fmt->fourcc;
++              return -EINVAL;
++      }
++
++      v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
++
++      ret = __subdev_set_format(dev, &mbus_fmt, node->pad_id);
++      if (ret) {
++              unicam_dbg(3, dev, "%s __subdev_set_format failed %d\n",
++                         __func__, ret);
++              return ret;
++      }
++
++      /* Just double check nothing has gone wrong */
++      if (mbus_fmt.code != fmt->code) {
++              unicam_dbg(3, dev,
++                         "%s subdev changed format on us, this should not happen\n",
++                         __func__);
++              return -EINVAL;
++      }
++
++      node->fmt = fmt;
++      node->v_fmt.fmt.pix.pixelformat = f->fmt.pix.pixelformat;
++      node->v_fmt.fmt.pix.bytesperline = f->fmt.pix.bytesperline;
++      unicam_reset_format(node);
++
++      unicam_dbg(3, dev,
++                 "%s %dx%d, mbus_fmt 0x%08X, V4L2 pix 0x%08X.\n",
++                 __func__, node->v_fmt.fmt.pix.width,
++                 node->v_fmt.fmt.pix.height, mbus_fmt.code,
++                 node->v_fmt.fmt.pix.pixelformat);
++
++      *f = node->v_fmt;
++
++      return 0;
++}
++
++static int unicam_enum_fmt_meta_cap(struct file *file, void *priv,
++                                  struct v4l2_fmtdesc *f)
++{
++      struct unicam_node *node = video_drvdata(file);
++      struct unicam_device *dev = node->dev;
++      const struct unicam_fmt *fmt;
++      u32 code;
++      int ret = 0;
++
++      if (node->pad_id != METADATA_PAD || f->index != 0)
++              return -EINVAL;
++
++      if (dev->sensor_embedded_data) {
++              struct v4l2_subdev_mbus_code_enum mbus_code = {
++                      .index = f->index,
++                      .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++                      .pad = METADATA_PAD,
++              };
++
++              ret = v4l2_subdev_call(dev->sensor, pad, enum_mbus_code, NULL,
++                                     &mbus_code);
++              if (ret < 0) {
++                      unicam_dbg(2, dev,
++                                 "subdev->enum_mbus_code idx 0 returned %d - index invalid\n",
++                                 ret);
++                      return -EINVAL;
++              }
++
++              code = mbus_code.code;
++      } else {
++              code = MEDIA_BUS_FMT_SENSOR_DATA;
++      }
++
++      fmt = find_format_by_code(code);
++      if (fmt)
++              f->pixelformat = fmt->fourcc;
++
++      return 0;
++}
++
++static int unicam_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_queue_setup(struct vb2_queue *vq,
++                            unsigned int *nbuffers,
++                            unsigned int *nplanes,
++                            unsigned int sizes[],
++                            struct device *alloc_devs[])
++{
++      struct unicam_node *node = vb2_get_drv_priv(vq);
++      struct unicam_device *dev = node->dev;
++      unsigned int size = node->pad_id == IMAGE_PAD ?
++                                  node->v_fmt.fmt.pix.sizeimage :
++                                  node->v_fmt.fmt.meta.buffersize;
++
++      if (vq->num_buffers + *nbuffers < 3)
++              *nbuffers = 3 - vq->num_buffers;
++
++      if (*nplanes) {
++              if (sizes[0] < size) {
++                      unicam_err(dev, "sizes[0] %i < size %u\n", sizes[0],
++                                 size);
++                      return -EINVAL;
++              }
++              size = sizes[0];
++      }
++
++      *nplanes = 1;
++      sizes[0] = size;
++
++      return 0;
++}
++
++static int unicam_buffer_prepare(struct vb2_buffer *vb)
++{
++      struct unicam_node *node = vb2_get_drv_priv(vb->vb2_queue);
++      struct unicam_device *dev = node->dev;
++      struct unicam_buffer *buf = to_unicam_buffer(vb);
++      unsigned long size;
++
++      if (WARN_ON(!node->fmt))
++              return -EINVAL;
++
++      size = node->pad_id == IMAGE_PAD ? node->v_fmt.fmt.pix.sizeimage :
++                                         node->v_fmt.fmt.meta.buffersize;
++      if (vb2_plane_size(vb, 0) < size) {
++              unicam_err(dev, "data will not fit into plane (%lu < %lu)\n",
++                         vb2_plane_size(vb, 0), size);
++              return -EINVAL;
++      }
++
++      vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
++      return 0;
++}
++
++static void unicam_buffer_queue(struct vb2_buffer *vb)
++{
++      struct unicam_node *node = vb2_get_drv_priv(vb->vb2_queue);
++      struct unicam_buffer *buf = to_unicam_buffer(vb);
++      unsigned long flags;
++
++      spin_lock_irqsave(&node->dma_queue_lock, flags);
++      list_add_tail(&buf->list, &node->dma_queue);
++      spin_unlock_irqrestore(&node->dma_queue_lock, flags);
++}
++
++static void unicam_set_packing_config(struct unicam_device *dev)
++{
++      u32 pack, unpack;
++      u32 val;
++
++      if (dev->node[IMAGE_PAD].v_fmt.fmt.pix.pixelformat ==
++          dev->node[IMAGE_PAD].fmt->fourcc) {
++              unpack = UNICAM_PUM_NONE;
++              pack = UNICAM_PPM_NONE;
++      } else {
++              switch (dev->node[IMAGE_PAD].fmt->depth) {
++              case 8:
++                      unpack = UNICAM_PUM_UNPACK8;
++                      break;
++              case 10:
++                      unpack = UNICAM_PUM_UNPACK10;
++                      break;
++              case 12:
++                      unpack = UNICAM_PUM_UNPACK12;
++                      break;
++              case 14:
++                      unpack = UNICAM_PUM_UNPACK14;
++                      break;
++              case 16:
++                      unpack = UNICAM_PUM_UNPACK16;
++                      break;
++              default:
++                      unpack = UNICAM_PUM_NONE;
++                      break;
++              }
++
++              /* Repacking is always to 16bpp */
++              pack = UNICAM_PPM_PACK16;
++      }
++
++      val = 0;
++      set_field(&val, unpack, UNICAM_PUM_MASK);
++      set_field(&val, pack, UNICAM_PPM_MASK);
++      reg_write(dev, UNICAM_IPIPE, val);
++}
++
++static void unicam_cfg_image_id(struct unicam_device *dev)
++{
++      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
++              /* CSI2 mode, hardcode VC 0 for now. */
++              reg_write(dev, UNICAM_IDI0,
++                        (0 << 6) | dev->node[IMAGE_PAD].fmt->csi_dt);
++      } else {
++              /* CCP2 mode */
++              reg_write(dev, UNICAM_IDI0,
++                        0x80 | dev->node[IMAGE_PAD].fmt->csi_dt);
++      }
++}
++
++static void unicam_enable_ed(struct unicam_device *dev)
++{
++      u32 val = reg_read(dev, UNICAM_DCS);
++
++      set_field(&val, 2, UNICAM_EDL_MASK);
++      /* Do not wrap at the end of the embedded data buffer */
++      set_field(&val, 0, UNICAM_DBOB);
++
++      reg_write(dev, UNICAM_DCS, val);
++}
++
++static void unicam_start_rx(struct unicam_device *dev, dma_addr_t *addr)
++{
++      int line_int_freq = dev->node[IMAGE_PAD].v_fmt.fmt.pix.height >> 2;
++      unsigned int size, i;
++      u32 val;
++
++      if (line_int_freq < 128)
++              line_int_freq = 128;
++
++      /* Enable lane clocks */
++      val = 1;
++      for (i = 0; i < dev->active_data_lanes; i++)
++              val = val << 2 | 1;
++      clk_write(dev, val);
++
++      /* Basic init */
++      reg_write(dev, UNICAM_CTRL, UNICAM_MEM);
++
++      /* Enable analogue control, and leave in reset. */
++      val = UNICAM_AR;
++      set_field(&val, 7, UNICAM_CTATADJ_MASK);
++      set_field(&val, 7, UNICAM_PTATADJ_MASK);
++      reg_write(dev, UNICAM_ANA, val);
++      usleep_range(1000, 2000);
++
++      /* Come out of reset */
++      reg_write_field(dev, UNICAM_ANA, 0, UNICAM_AR);
++
++      /* Peripheral reset */
++      reg_write_field(dev, UNICAM_CTRL, 1, UNICAM_CPR);
++      reg_write_field(dev, UNICAM_CTRL, 0, UNICAM_CPR);
++
++      reg_write_field(dev, UNICAM_CTRL, 0, UNICAM_CPE);
++
++      /* Enable Rx control. */
++      val = reg_read(dev, UNICAM_CTRL);
++      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
++              set_field(&val, UNICAM_CPM_CSI2, UNICAM_CPM_MASK);
++              set_field(&val, UNICAM_DCM_STROBE, UNICAM_DCM_MASK);
++      } else {
++              set_field(&val, UNICAM_CPM_CCP2, UNICAM_CPM_MASK);
++              set_field(&val, dev->bus_flags, UNICAM_DCM_MASK);
++      }
++      /* Packet framer timeout */
++      set_field(&val, 0xf, UNICAM_PFT_MASK);
++      set_field(&val, 128, UNICAM_OET_MASK);
++      reg_write(dev, UNICAM_CTRL, val);
++
++      reg_write(dev, UNICAM_IHWIN, 0);
++      reg_write(dev, UNICAM_IVWIN, 0);
++
++      /* AXI bus access QoS setup */
++      val = reg_read(dev, UNICAM_PRI);
++      set_field(&val, 0, UNICAM_BL_MASK);
++      set_field(&val, 0, UNICAM_BS_MASK);
++      set_field(&val, 0xe, UNICAM_PP_MASK);
++      set_field(&val, 8, UNICAM_NP_MASK);
++      set_field(&val, 2, UNICAM_PT_MASK);
++      set_field(&val, 1, UNICAM_PE);
++      reg_write(dev, UNICAM_PRI, val);
++
++      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;
++      set_field(&val, line_int_freq, UNICAM_LCIE_MASK);
++      reg_write(dev, UNICAM_ICTL, val);
++      reg_write(dev, UNICAM_STA, UNICAM_STA_MASK_ALL);
++      reg_write(dev, UNICAM_ISTA, UNICAM_ISTA_MASK_ALL);
++
++      /* tclk_term_en */
++      reg_write_field(dev, UNICAM_CLT, 2, UNICAM_CLT1_MASK);
++      /* tclk_settle */
++      reg_write_field(dev, UNICAM_CLT, 6, UNICAM_CLT2_MASK);
++      /* td_term_en */
++      reg_write_field(dev, UNICAM_DLT, 2, UNICAM_DLT1_MASK);
++      /* ths_settle */
++      reg_write_field(dev, UNICAM_DLT, 6, UNICAM_DLT2_MASK);
++      /* trx_enable */
++      reg_write_field(dev, UNICAM_DLT, 0, UNICAM_DLT3_MASK);
++
++      reg_write_field(dev, UNICAM_CTRL, 0, UNICAM_SOE);
++
++      /* Packet compare setup - required to avoid missing frame ends */
++      val = 0;
++      set_field(&val, 1, UNICAM_PCE);
++      set_field(&val, 1, UNICAM_GI);
++      set_field(&val, 1, UNICAM_CPH);
++      set_field(&val, 0, UNICAM_PCVC_MASK);
++      set_field(&val, 1, UNICAM_PCDT_MASK);
++      reg_write(dev, UNICAM_CMP0, val);
++
++      /* Enable clock lane and set up terminations */
++      val = 0;
++      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
++              /* CSI2 */
++              set_field(&val, 1, UNICAM_CLE);
++              set_field(&val, 1, UNICAM_CLLPE);
++              if (dev->bus_flags & V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) {
++                      set_field(&val, 1, UNICAM_CLTRE);
++                      set_field(&val, 1, UNICAM_CLHSE);
++              }
++      } else {
++              /* CCP2 */
++              set_field(&val, 1, UNICAM_CLE);
++              set_field(&val, 1, UNICAM_CLHSE);
++              set_field(&val, 1, UNICAM_CLTRE);
++      }
++      reg_write(dev, UNICAM_CLK, val);
++
++      /*
++       * Enable required data lanes with appropriate terminations.
++       * The same value needs to be written to UNICAM_DATn registers for
++       * the active lanes, and 0 for inactive ones.
++       */
++      val = 0;
++      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
++              /* CSI2 */
++              set_field(&val, 1, UNICAM_DLE);
++              set_field(&val, 1, UNICAM_DLLPE);
++              if (dev->bus_flags & V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) {
++                      set_field(&val, 1, UNICAM_DLTRE);
++                      set_field(&val, 1, UNICAM_DLHSE);
++              }
++      } else {
++              /* CCP2 */
++              set_field(&val, 1, UNICAM_DLE);
++              set_field(&val, 1, UNICAM_DLHSE);
++              set_field(&val, 1, UNICAM_DLTRE);
++      }
++      reg_write(dev, UNICAM_DAT0, val);
++
++      if (dev->active_data_lanes == 1)
++              val = 0;
++      reg_write(dev, UNICAM_DAT1, val);
++
++      if (dev->max_data_lanes > 2) {
++              /*
++               * Registers UNICAM_DAT2 and UNICAM_DAT3 only valid if the
++               * instance supports more than 2 data lanes.
++               */
++              if (dev->active_data_lanes == 2)
++                      val = 0;
++              reg_write(dev, UNICAM_DAT2, val);
++
++              if (dev->active_data_lanes == 3)
++                      val = 0;
++              reg_write(dev, UNICAM_DAT3, val);
++      }
++
++      reg_write(dev, UNICAM_IBLS,
++                dev->node[IMAGE_PAD].v_fmt.fmt.pix.bytesperline);
++      size = dev->node[IMAGE_PAD].v_fmt.fmt.pix.sizeimage;
++      unicam_wr_dma_addr(dev, addr[IMAGE_PAD], size, IMAGE_PAD);
++      unicam_set_packing_config(dev);
++      unicam_cfg_image_id(dev);
++
++      val = reg_read(dev, UNICAM_MISC);
++      set_field(&val, 1, UNICAM_FL0);
++      set_field(&val, 1, UNICAM_FL1);
++      reg_write(dev, UNICAM_MISC, val);
++
++      if (dev->node[METADATA_PAD].streaming && dev->sensor_embedded_data) {
++              size = dev->node[METADATA_PAD].v_fmt.fmt.meta.buffersize;
++              unicam_enable_ed(dev);
++              unicam_wr_dma_addr(dev, addr[METADATA_PAD], size, METADATA_PAD);
++      }
++
++      /* Enable peripheral */
++      reg_write_field(dev, UNICAM_CTRL, 1, UNICAM_CPE);
++
++      /* Load image pointers */
++      reg_write_field(dev, UNICAM_ICTL, 1, UNICAM_LIP_MASK);
++
++      /* 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)
++{
++      /* Analogue lane control disable */
++      reg_write_field(dev, UNICAM_ANA, 1, UNICAM_DDL);
++
++      /* Stop the output engine */
++      reg_write_field(dev, UNICAM_CTRL, 1, UNICAM_SOE);
++
++      /* Disable the data lanes. */
++      reg_write(dev, UNICAM_DAT0, 0);
++      reg_write(dev, UNICAM_DAT1, 0);
++
++      if (dev->max_data_lanes > 2) {
++              reg_write(dev, UNICAM_DAT2, 0);
++              reg_write(dev, UNICAM_DAT3, 0);
++      }
++
++      /* Peripheral reset */
++      reg_write_field(dev, UNICAM_CTRL, 1, UNICAM_CPR);
++      usleep_range(50, 100);
++      reg_write_field(dev, UNICAM_CTRL, 0, UNICAM_CPR);
++
++      /* Disable peripheral */
++      reg_write_field(dev, UNICAM_CTRL, 0, UNICAM_CPE);
++
++      /* Clear ED setup */
++      reg_write(dev, UNICAM_DCS, 0);
++
++      /* Disable all lane clocks */
++      clk_write(dev, 0);
++}
++
++static void unicam_return_buffers(struct unicam_node *node)
++{
++      struct unicam_buffer *buf, *tmp;
++      unsigned long flags;
++
++      spin_lock_irqsave(&node->dma_queue_lock, flags);
++      list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) {
++              list_del(&buf->list);
++              vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
++      }
++
++      if (node->cur_frm)
++              vb2_buffer_done(&node->cur_frm->vb.vb2_buf,
++                              VB2_BUF_STATE_ERROR);
++      if (node->next_frm && node->cur_frm != node->next_frm)
++              vb2_buffer_done(&node->next_frm->vb.vb2_buf,
++                              VB2_BUF_STATE_ERROR);
++
++      node->cur_frm = NULL;
++      node->next_frm = NULL;
++      spin_unlock_irqrestore(&node->dma_queue_lock, flags);
++}
++
++static int unicam_start_streaming(struct vb2_queue *vq, unsigned int count)
++{
++      struct unicam_node *node = vb2_get_drv_priv(vq);
++      struct unicam_device *dev = node->dev;
++      dma_addr_t buffer_addr[MAX_NODES] = { 0 };
++      unsigned long flags;
++      unsigned int i;
++      int ret;
++
++      node->streaming = true;
++      if (!unicam_all_nodes_streaming(dev)) {
++              unicam_dbg(3, dev, "Not all nodes are streaming yet.");
++              return 0;
++      }
++
++      dev->sequence = 0;
++      ret = unicam_runtime_get(dev);
++      if (ret < 0) {
++              unicam_dbg(3, dev, "unicam_runtime_get failed\n");
++              goto err_streaming;
++      }
++
++      /*
++       * TODO: Retrieve the number of active data lanes from the connected
++       * subdevice.
++       */
++      dev->active_data_lanes = dev->max_data_lanes;
++
++      ret = clk_set_rate(dev->clock, 100 * 1000 * 1000);
++      if (ret) {
++              unicam_err(dev, "failed to set up clock\n");
++              goto err_pm_put;
++      }
++
++      ret = clk_prepare_enable(dev->clock);
++      if (ret) {
++              unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
++              goto err_pm_put;
++      }
++
++      for (i = 0; i < ARRAY_SIZE(dev->node); i++) {
++              struct unicam_buffer *buf;
++
++              if (!dev->node[i].streaming)
++                      continue;
++
++              spin_lock_irqsave(&dev->node[i].dma_queue_lock, flags);
++              buf = list_first_entry(&dev->node[i].dma_queue,
++                                     struct unicam_buffer, list);
++              dev->node[i].cur_frm = buf;
++              dev->node[i].next_frm = buf;
++              list_del(&buf->list);
++              spin_unlock_irqrestore(&dev->node[i].dma_queue_lock, flags);
++
++              buffer_addr[i] =
++                      vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
++      }
++
++      unicam_start_rx(dev, buffer_addr);
++
++      ret = v4l2_subdev_call(dev->sensor, video, s_stream, 1);
++      if (ret < 0) {
++              unicam_err(dev, "stream on failed in subdev\n");
++              goto err_disable_unicam;
++      }
++
++      return 0;
++
++err_disable_unicam:
++      unicam_disable(dev);
++      clk_disable_unprepare(dev->clock);
++err_pm_put:
++      unicam_runtime_put(dev);
++err_streaming:
++      unicam_return_buffers(node);
++      node->streaming = false;
++
++      return ret;
++}
++
++static void unicam_stop_streaming(struct vb2_queue *vq)
++{
++      struct unicam_node *node = vb2_get_drv_priv(vq);
++      struct unicam_device *dev = node->dev;
++
++      node->streaming = false;
++
++      if (node->pad_id == IMAGE_PAD) {
++              /*
++               * Stop streaming the sensor and disable the peripheral.
++               * We cannot continue streaming embedded data with the
++               * image pad disabled.
++               */
++              if (v4l2_subdev_call(dev->sensor, video, s_stream, 0) < 0)
++                      unicam_err(dev, "stream off failed in subdev\n");
++
++              unicam_disable(dev);
++              clk_disable_unprepare(dev->clock);
++              unicam_runtime_put(dev);
++
++      } else if (node->pad_id == METADATA_PAD) {
++              /*
++               * Allow the hardware to spin in the dummy buffer.
++               * This is only really needed if the embedded data pad is
++               * disabled before the image pad.
++               */
++              unicam_wr_dma_addr(dev, node->dummy_buf_dma_addr,
++                                 DUMMY_BUF_SIZE, METADATA_PAD);
++      }
++
++      /* Clear all queued buffers for the node */
++      unicam_return_buffers(node);
++}
++
++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;
++
++      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;
++      }
++      sprintf(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, &current_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,
++      };
++
++      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;
++
++      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,
++                             &current_timings);
++
++      if (v4l2_match_dv_timings(timings, &current_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,
++      .wait_finish            = vb2_ops_wait_finish,
++      .queue_setup            = unicam_queue_setup,
++      .buf_prepare            = unicam_buffer_prepare,
++      .buf_queue              = unicam_buffer_queue,
++      .start_streaming        = unicam_start_streaming,
++      .stop_streaming         = unicam_stop_streaming,
++};
++
++/*
++ * unicam_v4l2_open : This function is based on the v4l2_fh_open helper
++ * function. It has been augmented to handle sensor subdevice power management,
++ */
++static int unicam_v4l2_open(struct file *file)
++{
++      struct unicam_node *node = video_drvdata(file);
++      struct unicam_device *dev = node->dev;
++      int ret;
++
++      mutex_lock(&node->lock);
++
++      ret = v4l2_fh_open(file);
++      if (ret) {
++              unicam_err(dev, "v4l2_fh_open failed\n");
++              goto unlock;
++      }
++
++      node->open++;
++
++      if (!v4l2_fh_is_singular_file(file))
++              goto unlock;
++
++      ret = v4l2_subdev_call(dev->sensor, core, s_power, 1);
++      if (ret < 0 && ret != -ENOIOCTLCMD) {
++              v4l2_fh_release(file);
++              node->open--;
++              goto unlock;
++      }
++
++      ret = 0;
++
++unlock:
++      mutex_unlock(&node->lock);
++      return ret;
++}
++
++static int unicam_v4l2_release(struct file *file)
++{
++      struct unicam_node *node = video_drvdata(file);
++      struct unicam_device *dev = node->dev;
++      struct v4l2_subdev *sd = dev->sensor;
++      bool fh_singular;
++      int ret;
++
++      mutex_lock(&node->lock);
++
++      fh_singular = v4l2_fh_is_singular_file(file);
++
++      ret = _vb2_fop_release(file, NULL);
++
++      if (fh_singular)
++              v4l2_subdev_call(sd, core, s_power, 0);
++
++      node->open--;
++      mutex_unlock(&node->lock);
++
++      return ret;
++}
++
++/* unicam capture driver file operations */
++static const struct v4l2_file_operations unicam_fops = {
++      .owner          = THIS_MODULE,
++      .open           = unicam_v4l2_open,
++      .release        = unicam_v4l2_release,
++      .read           = vb2_fop_read,
++      .poll           = vb2_fop_poll,
++      .unlocked_ioctl = video_ioctl2,
++      .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,
++                 struct v4l2_async_subdev *asd)
++{
++      struct unicam_device *unicam = to_unicam_device(notifier->v4l2_dev);
++
++      if (unicam->sensor) {
++              unicam_info(unicam, "Rejecting subdev %s (Already set!!)",
++                          subdev->name);
++              return 0;
++      }
++
++      unicam->sensor = subdev;
++      unicam_dbg(1, unicam, "Using sensor %s for capture\n", subdev->name);
++
++      return 0;
++}
++
++static void unicam_release(struct kref *kref)
++{
++      struct unicam_device *unicam =
++              container_of(kref, struct unicam_device, kref);
++
++      v4l2_ctrl_handler_free(&unicam->ctrl_handler);
++      media_device_cleanup(&unicam->mdev);
++
++      if (unicam->sensor_config)
++              v4l2_subdev_free_pad_config(unicam->sensor_config);
++
++      kfree(unicam);
++}
++
++static void unicam_put(struct unicam_device *unicam)
++{
++      kref_put(&unicam->kref, unicam_release);
++}
++
++static void unicam_get(struct unicam_device *unicam)
++{
++      kref_get(&unicam->kref);
++}
++
++static void unicam_node_release(struct video_device *vdev)
++{
++      struct unicam_node *node = video_get_drvdata(vdev);
++
++      unicam_put(node->dev);
++}
++
++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;
++      struct v4l2_mbus_framefmt mbus_fmt = {0};
++      const struct unicam_fmt *fmt;
++      int ret;
++
++      if (pad_id == IMAGE_PAD) {
++              ret = __subdev_get_format(unicam, &mbus_fmt, pad_id);
++              if (ret) {
++                      unicam_err(unicam, "Failed to get_format - ret %d\n",
++                                 ret);
++                      return ret;
++              }
++
++              fmt = find_format_by_code(mbus_fmt.code);
++              if (!fmt) {
++                      /*
++                       * Find the first format that the sensor and unicam both
++                       * support
++                       */
++                      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 (mbus_fmt.field != V4L2_FIELD_NONE) {
++                      /* Interlaced not supported - disable it now. */
++                      mbus_fmt.field = V4L2_FIELD_NONE;
++                      ret = __subdev_set_format(unicam, &mbus_fmt, pad_id);
++                      if (ret)
++                              return -EINVAL;
++              }
++
++              node->v_fmt.fmt.pix.pixelformat = fmt->fourcc ? fmt->fourcc
++                                              : fmt->repacked_fourcc;
++      } else {
++              /* 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->dev = unicam;
++      node->pad_id = pad_id;
++      node->fmt = fmt;
++
++      /* Read current subdev format */
++      unicam_reset_format(node);
++
++      if (v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
++              v4l2_std_id tvnorms;
++
++              if (WARN_ON(!v4l2_subdev_has_op(unicam->sensor, video,
++                                              g_tvnorms)))
++                      /*
++                       * Subdevice should not advertise s_std but not
++                       * g_tvnorms
++                       */
++                      return -EINVAL;
++
++              ret = v4l2_subdev_call(unicam->sensor, video,
++                                     g_tvnorms, &tvnorms);
++              if (WARN_ON(ret))
++                      return -EINVAL;
++              node->video_dev.tvnorms |= tvnorms;
++      }
++
++      spin_lock_init(&node->dma_queue_lock);
++      mutex_init(&node->lock);
++
++      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 the sensor subdevice has any controls, associate the node
++               *  with the ctrl handler to allow access from userland.
++               */
++              if (!list_empty(&unicam->ctrl_handler.ctrls))
++                      vdev->ctrl_handler = &unicam->ctrl_handler;
++      }
++
++      q = &node->buffer_queue;
++      q->type = type;
++      q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
++      q->drv_priv = node;
++      q->ops = &unicam_video_qops;
++      q->mem_ops = &vb2_dma_contig_memops;
++      q->buf_struct_size = sizeof(struct unicam_buffer);
++      q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
++      q->lock = &node->lock;
++      q->min_buffers_needed = 2;
++      q->dev = &unicam->pdev->dev;
++
++      ret = vb2_queue_init(q);
++      if (ret) {
++              unicam_err(unicam, "vb2_queue_init() failed\n");
++              return ret;
++      }
++
++      INIT_LIST_HEAD(&node->dma_queue);
++
++      vdev->release = unicam_node_release;
++      vdev->fops = &unicam_fops;
++      vdev->ioctl_ops = &unicam_ioctl_ops;
++      vdev->v4l2_dev = &unicam->v4l2_dev;
++      vdev->vfl_dir = VFL_DIR_RX;
++      vdev->queue = q;
++      vdev->lock = &node->lock;
++      vdev->device_caps = (pad_id == IMAGE_PAD) ?
++                          (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING) :
++                          (V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING);
++
++      /* Define the device names */
++      snprintf(vdev->name, sizeof(vdev->name), "%s-%s", UNICAM_MODULE_NAME,
++               pad_id == IMAGE_PAD ? "image" : "embedded");
++
++      video_set_drvdata(vdev, node);
++      if (pad_id == IMAGE_PAD)
++              vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT;
++      node->pad.flags = MEDIA_PAD_FL_SINK;
++      media_entity_pads_init(&vdev->entity, 1, &node->pad);
++
++      node->dummy_buf_cpu_addr = dma_alloc_coherent(&unicam->pdev->dev,
++                                                    DUMMY_BUF_SIZE,
++                                                    &node->dummy_buf_dma_addr,
++                                                    GFP_KERNEL);
++      if (!node->dummy_buf_cpu_addr) {
++              unicam_err(unicam, "Unable to allocate dummy buffer.\n");
++              return -ENOMEM;
++      }
++
++      if (pad_id == METADATA_PAD) {
++              v4l2_disable_ioctl(vdev, VIDIOC_DQEVENT);
++              v4l2_disable_ioctl(vdev, VIDIOC_SUBSCRIBE_EVENT);
++              v4l2_disable_ioctl(vdev, VIDIOC_UNSUBSCRIBE_EVENT);
++      }
++      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) {
++              unicam_err(unicam, "Unable to register video device %s\n",
++                         vdev->name);
++              return ret;
++      }
++
++      /*
++       * Acquire a reference to unicam, which will be released when the video
++       * device will be unregistered and userspace will have closed all open
++       * file handles.
++       */
++      unicam_get(unicam);
++      node->registered = true;
++
++      if (pad_id != METADATA_PAD || unicam->sensor_embedded_data) {
++              ret = media_create_pad_link(&unicam->sensor->entity, pad_id,
++                                          &node->video_dev.entity, 0,
++                                          MEDIA_LNK_FL_ENABLED |
++                                          MEDIA_LNK_FL_IMMUTABLE);
++              if (ret)
++                      unicam_err(unicam, "Unable to create pad link for %s\n",
++                                 vdev->name);
++      }
++
++      return ret;
++}
++
++static void unregister_nodes(struct unicam_device *unicam)
++{
++      unsigned int i;
++
++      for (i = 0; i < ARRAY_SIZE(unicam->node); i++) {
++              struct unicam_node *node = &unicam->node[i];
++
++              if (node->dummy_buf_cpu_addr) {
++                      dma_free_coherent(&unicam->pdev->dev, DUMMY_BUF_SIZE,
++                                        node->dummy_buf_cpu_addr,
++                                        node->dummy_buf_dma_addr);
++              }
++
++              if (node->registered) {
++                      node->registered = false;
++                      video_unregister_device(&node->video_dev);
++              }
++      }
++}
++
++static int unicam_probe_complete(struct unicam_device *unicam)
++{
++      int ret;
++
++      unicam->v4l2_dev.notify = unicam_notify;
++
++      unicam->sensor_config = v4l2_subdev_alloc_pad_config(unicam->sensor);
++      if (!unicam->sensor_config)
++              return -ENOMEM;
++
++      unicam->sensor_embedded_data = (unicam->sensor->entity.num_pads >= 2);
++
++      ret = register_node(unicam, &unicam->node[IMAGE_PAD],
++                          V4L2_BUF_TYPE_VIDEO_CAPTURE, IMAGE_PAD);
++      if (ret) {
++              unicam_err(unicam, "Unable to register image video device.\n");
++              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;
++      }
++
++      ret = v4l2_device_register_ro_subdev_nodes(&unicam->v4l2_dev);
++      if (ret) {
++              unicam_err(unicam, "Unable to register subdev nodes.\n");
++              goto unregister;
++      }
++
++      /*
++       * Release the initial reference, all references are now owned by the
++       * video devices.
++       */
++      unicam_put(unicam);
++      return 0;
++
++unregister:
++      unregister_nodes(unicam);
++      unicam_put(unicam);
++
++      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,
++};
++
++static int of_unicam_connect_subdevs(struct unicam_device *dev)
++{
++      struct platform_device *pdev = dev->pdev;
++      struct v4l2_fwnode_endpoint ep = { 0 };
++      struct device_node *ep_node;
++      struct device_node *sensor_node;
++      unsigned int lane;
++      int ret = -EINVAL;
++
++      if (of_property_read_u32(pdev->dev.of_node, "brcm,num-data-lanes",
++                               &dev->max_data_lanes) < 0) {
++              unicam_err(dev, "number of data lanes not set\n");
++              return -EINVAL;
++      }
++
++      /* Get the local endpoint and remote device. */
++      ep_node = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
++      if (!ep_node) {
++              unicam_dbg(3, dev, "can't get next endpoint\n");
++              return -EINVAL;
++      }
++
++      unicam_dbg(3, dev, "ep_node is %pOF\n", ep_node);
++
++      sensor_node = of_graph_get_remote_port_parent(ep_node);
++      if (!sensor_node) {
++              unicam_dbg(3, dev, "can't get remote parent\n");
++              goto cleanup_exit;
++      }
++
++      unicam_dbg(1, dev, "found subdevice %pOF\n", sensor_node);
++
++      /* Parse the local endpoint and validate its configuration. */
++      v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), &ep);
++
++      unicam_dbg(3, dev, "parsed local endpoint, bus_type %u\n",
++                 ep.bus_type);
++
++      dev->bus_type = ep.bus_type;
++
++      switch (ep.bus_type) {
++      case V4L2_MBUS_CSI2_DPHY:
++              switch (ep.bus.mipi_csi2.num_data_lanes) {
++              case 1:
++              case 2:
++              case 4:
++                      break;
++
++              default:
++                      unicam_err(dev, "subdevice %pOF: %u data lanes not supported\n",
++                                 sensor_node,
++                                 ep.bus.mipi_csi2.num_data_lanes);
++                      goto cleanup_exit;
++              }
++
++              for (lane = 0; lane < ep.bus.mipi_csi2.num_data_lanes; lane++) {
++                      if (ep.bus.mipi_csi2.data_lanes[lane] != lane + 1) {
++                              unicam_err(dev, "subdevice %pOF: data lanes reordering not supported\n",
++                                         sensor_node);
++                              goto cleanup_exit;
++                      }
++              }
++
++              if (ep.bus.mipi_csi2.num_data_lanes > dev->max_data_lanes) {
++                      unicam_err(dev, "subdevice requires %u data lanes when %u are supported\n",
++                                 ep.bus.mipi_csi2.num_data_lanes,
++                                 dev->max_data_lanes);
++              }
++
++              dev->max_data_lanes = ep.bus.mipi_csi2.num_data_lanes;
++              dev->bus_flags = ep.bus.mipi_csi2.flags;
++
++              break;
++
++      case V4L2_MBUS_CCP2:
++              if (ep.bus.mipi_csi1.clock_lane != 0 ||
++                  ep.bus.mipi_csi1.data_lane != 1) {
++                      unicam_err(dev, "subdevice %pOF: unsupported lanes configuration\n",
++                                 sensor_node);
++                      goto cleanup_exit;
++              }
++
++              dev->max_data_lanes = 1;
++              dev->bus_flags = ep.bus.mipi_csi1.strobe;
++              break;
++
++      default:
++              /* Unsupported bus type */
++              unicam_err(dev, "subdevice %pOF: unsupported bus type %u\n",
++                         sensor_node, ep.bus_type);
++              goto cleanup_exit;
++      }
++
++      unicam_dbg(3, dev, "subdevice %pOF: %s bus, %u data lanes, flags=0x%08x\n",
++                 sensor_node,
++                 dev->bus_type == V4L2_MBUS_CSI2_DPHY ? "CSI-2" : "CCP2",
++                 dev->max_data_lanes, dev->bus_flags);
++
++      /* Initialize and register the async notifier. */
++      v4l2_async_notifier_init(&dev->notifier);
++      dev->notifier.ops = &unicam_async_ops;
++
++      dev->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
++      dev->asd.match.fwnode = of_fwnode_handle(sensor_node);
++      ret = v4l2_async_notifier_add_subdev(&dev->notifier, &dev->asd);
++      if (ret) {
++              unicam_err(dev, "Error adding subdevice: %d\n", ret);
++              goto cleanup_exit;
++      }
++
++      ret = v4l2_async_notifier_register(&dev->v4l2_dev, &dev->notifier);
++      if (ret) {
++              unicam_err(dev, "Error registering async notifier: %d\n", ret);
++              ret = -EINVAL;
++      }
++
++cleanup_exit:
++      of_node_put(sensor_node);
++      of_node_put(ep_node);
++
++      return ret;
++}
++
++static int unicam_probe(struct platform_device *pdev)
++{
++      struct unicam_device *unicam;
++      int ret;
++
++      unicam = kzalloc(sizeof(*unicam), GFP_KERNEL);
++      if (!unicam)
++              return -ENOMEM;
++
++      kref_init(&unicam->kref);
++      unicam->pdev = pdev;
++
++      unicam->base = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(unicam->base)) {
++              unicam_err(unicam, "Failed to get main io block\n");
++              ret = PTR_ERR(unicam->base);
++              goto err_unicam_put;
++      }
++
++      unicam->clk_gate_base = devm_platform_ioremap_resource(pdev, 1);
++      if (IS_ERR(unicam->clk_gate_base)) {
++              unicam_err(unicam, "Failed to get 2nd io block\n");
++              ret = PTR_ERR(unicam->clk_gate_base);
++              goto err_unicam_put;
++      }
++
++      unicam->clock = devm_clk_get(&pdev->dev, "lp");
++      if (IS_ERR(unicam->clock)) {
++              unicam_err(unicam, "Failed to get clock\n");
++              ret = PTR_ERR(unicam->clock);
++              goto err_unicam_put;
++      }
++
++      ret = platform_get_irq(pdev, 0);
++      if (ret <= 0) {
++              dev_err(&pdev->dev, "No IRQ resource\n");
++              ret = -EINVAL;
++              goto err_unicam_put;
++      }
++
++      ret = devm_request_irq(&pdev->dev, ret, unicam_isr, 0,
++                             "unicam_capture0", unicam);
++      if (ret) {
++              dev_err(&pdev->dev, "Unable to request interrupt\n");
++              ret = -EINVAL;
++              goto err_unicam_put;
++      }
++
++      unicam->mdev.dev = &pdev->dev;
++      strscpy(unicam->mdev.model, UNICAM_MODULE_NAME,
++              sizeof(unicam->mdev.model));
++      strscpy(unicam->mdev.serial, "", sizeof(unicam->mdev.serial));
++      snprintf(unicam->mdev.bus_info, sizeof(unicam->mdev.bus_info),
++               "platform:%s", dev_name(&pdev->dev));
++      unicam->mdev.hw_revision = 0;
++
++      media_device_init(&unicam->mdev);
++
++      unicam->v4l2_dev.mdev = &unicam->mdev;
++
++      ret = v4l2_device_register(&pdev->dev, &unicam->v4l2_dev);
++      if (ret) {
++              unicam_err(unicam,
++                         "Unable to register v4l2 device.\n");
++              goto err_unicam_put;
++      }
++
++      ret = media_device_register(&unicam->mdev);
++      if (ret < 0) {
++              unicam_err(unicam,
++                         "Unable to register media-controller device.\n");
++              goto err_v4l2_unregister;
++      }
++
++      /* Reserve space for the controls */
++      ret = v4l2_ctrl_handler_init(&unicam->ctrl_handler, 16);
++      if (ret < 0)
++              goto err_media_unregister;
++
++      /* set the driver data in platform device */
++      platform_set_drvdata(pdev, unicam);
++
++      ret = of_unicam_connect_subdevs(unicam);
++      if (ret) {
++              dev_err(&pdev->dev, "Failed to connect subdevs\n");
++              goto err_media_unregister;
++      }
++
++      /* Enable the block power domain */
++      pm_runtime_enable(&pdev->dev);
++
++      return 0;
++
++err_media_unregister:
++      media_device_unregister(&unicam->mdev);
++err_v4l2_unregister:
++      v4l2_device_unregister(&unicam->v4l2_dev);
++err_unicam_put:
++      unicam_put(unicam);
++
++      return ret;
++}
++
++static int unicam_remove(struct platform_device *pdev)
++{
++      struct unicam_device *unicam = platform_get_drvdata(pdev);
++
++      unicam_dbg(2, unicam, "%s\n", __func__);
++
++      v4l2_async_notifier_unregister(&unicam->notifier);
++      v4l2_device_unregister(&unicam->v4l2_dev);
++      media_device_unregister(&unicam->mdev);
++      unregister_nodes(unicam);
++
++      pm_runtime_disable(&pdev->dev);
++
++      return 0;
++}
++
++static const struct of_device_id unicam_of_match[] = {
++      { .compatible = "brcm,bcm2835-unicam", },
++      { /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(of, unicam_of_match);
++
++static struct platform_driver unicam_driver = {
++      .probe          = unicam_probe,
++      .remove         = unicam_remove,
++      .driver = {
++              .name   = UNICAM_MODULE_NAME,
++              .of_match_table = of_match_ptr(unicam_of_match),
++      },
++};
++
++module_platform_driver(unicam_driver);
++
++MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com>");
++MODULE_DESCRIPTION("BCM2835 Unicam driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(UNICAM_VERSION);
+--- /dev/null
++++ b/drivers/media/platform/bcm2835/vc4-regs-unicam.h
+@@ -0,0 +1,253 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++
++/*
++ * Copyright (C) 2017-2020 Raspberry Pi Trading.
++ * Dave Stevenson <dave.stevenson@raspberrypi.com>
++ */
++
++#ifndef VC4_REGS_UNICAM_H
++#define VC4_REGS_UNICAM_H
++
++/*
++ * The following values are taken from files found within the code drop
++ * made by Broadcom for the BCM21553 Graphics Driver, predominantly in
++ * brcm_usrlib/dag/vmcsx/vcinclude/hardware_vc4.h.
++ * They have been modified to be only the register offset.
++ */
++#define UNICAM_CTRL   0x000
++#define UNICAM_STA    0x004
++#define UNICAM_ANA    0x008
++#define UNICAM_PRI    0x00c
++#define UNICAM_CLK    0x010
++#define UNICAM_CLT    0x014
++#define UNICAM_DAT0   0x018
++#define UNICAM_DAT1   0x01c
++#define UNICAM_DAT2   0x020
++#define UNICAM_DAT3   0x024
++#define UNICAM_DLT    0x028
++#define UNICAM_CMP0   0x02c
++#define UNICAM_CMP1   0x030
++#define UNICAM_CAP0   0x034
++#define UNICAM_CAP1   0x038
++#define UNICAM_ICTL   0x100
++#define UNICAM_ISTA   0x104
++#define UNICAM_IDI0   0x108
++#define UNICAM_IPIPE  0x10c
++#define UNICAM_IBSA0  0x110
++#define UNICAM_IBEA0  0x114
++#define UNICAM_IBLS   0x118
++#define UNICAM_IBWP   0x11c
++#define UNICAM_IHWIN  0x120
++#define UNICAM_IHSTA  0x124
++#define UNICAM_IVWIN  0x128
++#define UNICAM_IVSTA  0x12c
++#define UNICAM_ICC    0x130
++#define UNICAM_ICS    0x134
++#define UNICAM_IDC    0x138
++#define UNICAM_IDPO   0x13c
++#define UNICAM_IDCA   0x140
++#define UNICAM_IDCD   0x144
++#define UNICAM_IDS    0x148
++#define UNICAM_DCS    0x200
++#define UNICAM_DBSA0  0x204
++#define UNICAM_DBEA0  0x208
++#define UNICAM_DBWP   0x20c
++#define UNICAM_DBCTL  0x300
++#define UNICAM_IBSA1  0x304
++#define UNICAM_IBEA1  0x308
++#define UNICAM_IDI1   0x30c
++#define UNICAM_DBSA1  0x310
++#define UNICAM_DBEA1  0x314
++#define UNICAM_MISC   0x400
++
++/*
++ * The following bitmasks are from the kernel released by Broadcom
++ * for Android - https://android.googlesource.com/kernel/bcm/
++ * The Rhea, Hawaii, and Java chips all contain the same VideoCore4
++ * Unicam block as BCM2835, as defined in eg
++ * arch/arm/mach-rhea/include/mach/rdb_A0/brcm_rdb_cam.h and similar.
++ * Values reworked to use the kernel BIT and GENMASK macros.
++ *
++ * Some of the bit mnenomics have been amended to match the datasheet.
++ */
++/* UNICAM_CTRL Register */
++#define UNICAM_CPE            BIT(0)
++#define UNICAM_MEM            BIT(1)
++#define UNICAM_CPR            BIT(2)
++#define UNICAM_CPM_MASK               GENMASK(3, 3)
++#define UNICAM_CPM_CSI2               0
++#define UNICAM_CPM_CCP2               1
++#define UNICAM_SOE            BIT(4)
++#define UNICAM_DCM_MASK               GENMASK(5, 5)
++#define UNICAM_DCM_STROBE     0
++#define UNICAM_DCM_DATA               1
++#define UNICAM_SLS            BIT(6)
++#define UNICAM_PFT_MASK               GENMASK(11, 8)
++#define UNICAM_OET_MASK               GENMASK(20, 12)
++
++/* UNICAM_STA Register */
++#define UNICAM_SYN            BIT(0)
++#define UNICAM_CS             BIT(1)
++#define UNICAM_SBE            BIT(2)
++#define UNICAM_PBE            BIT(3)
++#define UNICAM_HOE            BIT(4)
++#define UNICAM_PLE            BIT(5)
++#define UNICAM_SSC            BIT(6)
++#define UNICAM_CRCE           BIT(7)
++#define UNICAM_OES            BIT(8)
++#define UNICAM_IFO            BIT(9)
++#define UNICAM_OFO            BIT(10)
++#define UNICAM_BFO            BIT(11)
++#define UNICAM_DL             BIT(12)
++#define UNICAM_PS             BIT(13)
++#define UNICAM_IS             BIT(14)
++#define UNICAM_PI0            BIT(15)
++#define UNICAM_PI1            BIT(16)
++#define UNICAM_FSI_S          BIT(17)
++#define UNICAM_FEI_S          BIT(18)
++#define UNICAM_LCI_S          BIT(19)
++#define UNICAM_BUF0_RDY               BIT(20)
++#define UNICAM_BUF0_NO                BIT(21)
++#define UNICAM_BUF1_RDY               BIT(22)
++#define UNICAM_BUF1_NO                BIT(23)
++#define UNICAM_DI             BIT(24)
++
++#define UNICAM_STA_MASK_ALL \
++              (UNICAM_DL + \
++              UNICAM_SBE + \
++              UNICAM_PBE + \
++              UNICAM_HOE + \
++              UNICAM_PLE + \
++              UNICAM_SSC + \
++              UNICAM_CRCE + \
++              UNICAM_IFO + \
++              UNICAM_OFO + \
++              UNICAM_PS + \
++              UNICAM_PI0 + \
++              UNICAM_PI1)
++
++/* UNICAM_ANA Register */
++#define UNICAM_APD            BIT(0)
++#define UNICAM_BPD            BIT(1)
++#define UNICAM_AR             BIT(2)
++#define UNICAM_DDL            BIT(3)
++#define UNICAM_CTATADJ_MASK   GENMASK(7, 4)
++#define UNICAM_PTATADJ_MASK   GENMASK(11, 8)
++
++/* UNICAM_PRI Register */
++#define UNICAM_PE             BIT(0)
++#define UNICAM_PT_MASK                GENMASK(2, 1)
++#define UNICAM_NP_MASK                GENMASK(7, 4)
++#define UNICAM_PP_MASK                GENMASK(11, 8)
++#define UNICAM_BS_MASK                GENMASK(15, 12)
++#define UNICAM_BL_MASK                GENMASK(17, 16)
++
++/* UNICAM_CLK Register */
++#define UNICAM_CLE            BIT(0)
++#define UNICAM_CLPD           BIT(1)
++#define UNICAM_CLLPE          BIT(2)
++#define UNICAM_CLHSE          BIT(3)
++#define UNICAM_CLTRE          BIT(4)
++#define UNICAM_CLAC_MASK      GENMASK(8, 5)
++#define UNICAM_CLSTE          BIT(29)
++
++/* UNICAM_CLT Register */
++#define UNICAM_CLT1_MASK      GENMASK(7, 0)
++#define UNICAM_CLT2_MASK      GENMASK(15, 8)
++
++/* UNICAM_DATn Registers */
++#define UNICAM_DLE            BIT(0)
++#define UNICAM_DLPD           BIT(1)
++#define UNICAM_DLLPE          BIT(2)
++#define UNICAM_DLHSE          BIT(3)
++#define UNICAM_DLTRE          BIT(4)
++#define UNICAM_DLSM           BIT(5)
++#define UNICAM_DLFO           BIT(28)
++#define UNICAM_DLSTE          BIT(29)
++
++#define UNICAM_DAT_MASK_ALL (UNICAM_DLSTE + UNICAM_DLFO)
++
++/* UNICAM_DLT Register */
++#define UNICAM_DLT1_MASK      GENMASK(7, 0)
++#define UNICAM_DLT2_MASK      GENMASK(15, 8)
++#define UNICAM_DLT3_MASK      GENMASK(23, 16)
++
++/* UNICAM_ICTL Register */
++#define UNICAM_FSIE           BIT(0)
++#define UNICAM_FEIE           BIT(1)
++#define UNICAM_IBOB           BIT(2)
++#define UNICAM_FCM            BIT(3)
++#define UNICAM_TFC            BIT(4)
++#define UNICAM_LIP_MASK               GENMASK(6, 5)
++#define UNICAM_LCIE_MASK      GENMASK(28, 16)
++
++/* UNICAM_IDI0/1 Register */
++#define UNICAM_ID0_MASK               GENMASK(7, 0)
++#define UNICAM_ID1_MASK               GENMASK(15, 8)
++#define UNICAM_ID2_MASK               GENMASK(23, 16)
++#define UNICAM_ID3_MASK               GENMASK(31, 24)
++
++/* UNICAM_ISTA Register */
++#define UNICAM_FSI            BIT(0)
++#define UNICAM_FEI            BIT(1)
++#define UNICAM_LCI            BIT(2)
++
++#define UNICAM_ISTA_MASK_ALL (UNICAM_FSI + UNICAM_FEI + UNICAM_LCI)
++
++/* UNICAM_IPIPE Register */
++#define UNICAM_PUM_MASK               GENMASK(2, 0)
++              /* Unpacking modes */
++              #define UNICAM_PUM_NONE         0
++              #define UNICAM_PUM_UNPACK6      1
++              #define UNICAM_PUM_UNPACK7      2
++              #define UNICAM_PUM_UNPACK8      3
++              #define UNICAM_PUM_UNPACK10     4
++              #define UNICAM_PUM_UNPACK12     5
++              #define UNICAM_PUM_UNPACK14     6
++              #define UNICAM_PUM_UNPACK16     7
++#define UNICAM_DDM_MASK               GENMASK(6, 3)
++#define UNICAM_PPM_MASK               GENMASK(9, 7)
++              /* Packing modes */
++              #define UNICAM_PPM_NONE         0
++              #define UNICAM_PPM_PACK8        1
++              #define UNICAM_PPM_PACK10       2
++              #define UNICAM_PPM_PACK12       3
++              #define UNICAM_PPM_PACK14       4
++              #define UNICAM_PPM_PACK16       5
++#define UNICAM_DEM_MASK               GENMASK(11, 10)
++#define UNICAM_DEBL_MASK      GENMASK(14, 12)
++#define UNICAM_ICM_MASK               GENMASK(16, 15)
++#define UNICAM_IDM_MASK               GENMASK(17, 17)
++
++/* UNICAM_ICC Register */
++#define UNICAM_ICFL_MASK      GENMASK(4, 0)
++#define UNICAM_ICFH_MASK      GENMASK(9, 5)
++#define UNICAM_ICST_MASK      GENMASK(12, 10)
++#define UNICAM_ICLT_MASK      GENMASK(15, 13)
++#define UNICAM_ICLL_MASK      GENMASK(31, 16)
++
++/* UNICAM_DCS Register */
++#define UNICAM_DIE            BIT(0)
++#define UNICAM_DIM            BIT(1)
++#define UNICAM_DBOB           BIT(3)
++#define UNICAM_FDE            BIT(4)
++#define UNICAM_LDP            BIT(5)
++#define UNICAM_EDL_MASK               GENMASK(15, 8)
++
++/* UNICAM_DBCTL Register */
++#define UNICAM_DBEN           BIT(0)
++#define UNICAM_BUF0_IE                BIT(1)
++#define UNICAM_BUF1_IE                BIT(2)
++
++/* UNICAM_CMP[0,1] register */
++#define UNICAM_PCE            BIT(31)
++#define UNICAM_GI             BIT(9)
++#define UNICAM_CPH            BIT(8)
++#define UNICAM_PCVC_MASK      GENMASK(7, 6)
++#define UNICAM_PCDT_MASK      GENMASK(5, 0)
++
++/* UNICAM_MISC register */
++#define UNICAM_FL0            BIT(6)
++#define UNICAM_FL1            BIT(9)
++
++#endif
diff --git a/target/linux/bcm27xx/patches-5.4/950-0807-media-bcm2835-unicam-Add-support-for-get_mbus_config.patch b/target/linux/bcm27xx/patches-5.4/950-0807-media-bcm2835-unicam-Add-support-for-get_mbus_config.patch
new file mode 100644 (file)
index 0000000..8e3cef0
--- /dev/null
@@ -0,0 +1,56 @@
+From f1ab20a9584c97eddf07d4f8937f0aff42bd1038 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 23 Jun 2020 14:32:51 +0100
+Subject: [PATCH] media: bcm2835-unicam: Add support for
+ get_mbus_config to set num lanes
+
+Use the get_mbus_config pad subdev call to allow a source to use
+fewer than the number of CSI2 lanes defined in device tree.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 31 ++++++++++++++++---
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1639,12 +1639,35 @@ static int unicam_start_streaming(struct
+               goto err_streaming;
+       }
+-      /*
+-       * TODO: Retrieve the number of active data lanes from the connected
+-       * subdevice.
+-       */
+       dev->active_data_lanes = dev->max_data_lanes;
++      if (dev->bus_type == V4L2_MBUS_CSI2_DPHY) {
++              struct v4l2_mbus_config mbus_config = { 0 };
++
++              ret = v4l2_subdev_call(dev->sensor, pad, get_mbus_config,
++                                     0, &mbus_config);
++              if (ret < 0 && ret != -ENOIOCTLCMD) {
++                      unicam_dbg(3, dev, "g_mbus_config failed\n");
++                      goto err_pm_put;
++              }
++
++              dev->active_data_lanes =
++                      (mbus_config.flags & V4L2_MBUS_CSI2_LANE_MASK) >>
++                                      __ffs(V4L2_MBUS_CSI2_LANE_MASK);
++              if (!dev->active_data_lanes)
++                      dev->active_data_lanes = dev->max_data_lanes;
++              if (dev->active_data_lanes > dev->max_data_lanes) {
++                      unicam_err(dev, "Device has requested %u data lanes, which is >%u configured in DT\n",
++                                 dev->active_data_lanes,
++                                 dev->max_data_lanes);
++                      ret = -EINVAL;
++                      goto err_pm_put;
++              }
++      }
++
++      unicam_dbg(1, dev, "Running with %u data lanes\n",
++                 dev->active_data_lanes);
++
+       ret = clk_set_rate(dev->clock, 100 * 1000 * 1000);
+       if (ret) {
+               unicam_err(dev, "failed to set up clock\n");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0808-media-bcm2835-unicam-Always-service-interrupts.patch b/target/linux/bcm27xx/patches-5.4/950-0808-media-bcm2835-unicam-Always-service-interrupts.patch
new file mode 100644 (file)
index 0000000..371013f
--- /dev/null
@@ -0,0 +1,51 @@
+From b493e2a03c1780ae1ba09a9de58474c17a33310d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 13 May 2020 18:28:27 +0100
+Subject: [PATCH] media: bcm2835-unicam: Always service interrupts
+
+From when bringing up the driver, there was a check in the isr
+to ignore interrupts (claiming them handled) should the driver
+not be streaming.
+
+The VPU now will not register a camera driver if it finds a
+CSI2 node enabled in device tree, therefore this flawed check is
+redundant.
+
+https://github.com/raspberrypi/linux/issues/3602
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 15 ---------------
+ 1 file changed, 15 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -772,12 +772,6 @@ static bool unicam_all_nodes_streaming(s
+       return ret;
+ }
+-static bool unicam_all_nodes_disabled(struct unicam_device *dev)
+-{
+-      return !dev->node[IMAGE_PAD].streaming &&
+-             !dev->node[METADATA_PAD].streaming;
+-}
+-
+ static void unicam_queue_event_sof(struct unicam_device *unicam)
+ {
+       struct v4l2_event event = {
+@@ -805,15 +799,6 @@ static irqreturn_t unicam_isr(int irq, v
+       u32 ista, sta;
+       u64 ts;
+-      /*
+-       * Don't service interrupts if not streaming.
+-       * Avoids issues if the VPU should enable the
+-       * peripheral without the kernel knowing (that
+-       * shouldn't happen, but causes issues if it does).
+-       */
+-      if (unicam_all_nodes_disabled(unicam))
+-              return IRQ_NONE;
+-
+       sta = reg_read(unicam, UNICAM_STA);
+       /* Write value back to clear the interrupts */
+       reg_write(unicam, UNICAM_STA, sta);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0809-media-bcm2835-unicam-Fix-uninitialized-warning.patch b/target/linux/bcm27xx/patches-5.4/950-0809-media-bcm2835-unicam-Fix-uninitialized-warning.patch
new file mode 100644 (file)
index 0000000..1935c6b
--- /dev/null
@@ -0,0 +1,21 @@
+From bea7aa3af93ab5eb9b0f993230a802e65023081e Mon Sep 17 00:00:00 2001
+From: Jacko Dirks <jdirks.linuxdev@gmail.com>
+Date: Tue, 5 May 2020 14:33:31 +0200
+Subject: [PATCH] media: bcm2835: unicam: Fix uninitialized warning
+
+Signed-off-by: Jacko Dirks <jdirks.linuxdev@gmail.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -994,7 +994,7 @@ const struct unicam_fmt *get_first_suppo
+       struct v4l2_subdev_mbus_code_enum mbus_code;
+       const struct unicam_fmt *fmt = NULL;
+       unsigned int i;
+-      int ret;
++      int ret = 0;
+       for (i = 0; ret != -EINVAL && ret != -ENOIOCTLCMD; ++i) {
+               memset(&mbus_code, 0, sizeof(mbus_code));
diff --git a/target/linux/bcm27xx/patches-5.4/950-0810-media-bcm2835-unicam-Fixup-review-comments-from-Hans.patch b/target/linux/bcm27xx/patches-5.4/950-0810-media-bcm2835-unicam-Fixup-review-comments-from-Hans.patch
new file mode 100644 (file)
index 0000000..18565a7
--- /dev/null
@@ -0,0 +1,242 @@
+From 30351afb528e439a48960443c028b6b9c236c55a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 23 Jun 2020 15:14:05 +0100
+Subject: [PATCH] media: bcm2835-unicam: Fixup review comments from
+ Hans.
+
+Updates the driver based on the upstream review comments from
+Hans Verkuil at https://patchwork.linuxtv.org/patch/63531/
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/Kconfig        | 12 ++--
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 70 ++++++++-----------
+ 2 files changed, 39 insertions(+), 43 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/Kconfig
++++ b/drivers/media/platform/bcm2835/Kconfig
+@@ -1,15 +1,19 @@
+ # Broadcom VideoCore4 V4L2 camera support
+ config VIDEO_BCM2835_UNICAM
+-      tristate "Broadcom BCM2835 Unicam video capture driver"
++      tristate "Broadcom BCM283x/BCM271x Unicam video capture driver"
+       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+       depends on ARCH_BCM2835 || COMPILE_TEST
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_FWNODE
+       help
+-        Say Y here to enable support for the BCM2835 CSI-2 receiver. This is a
+-        V4L2 driver that controls the CSI-2 receiver directly, independently
+-        from the VC4 firmware.
++        Say Y here to enable support for the BCM283x/BCM271x CSI-2 receiver.
++        This is a V4L2 driver that controls the CSI-2 receiver directly,
++        independently from the VC4 firmware.
++        This driver is mutually exclusive with the use of bcm2835-camera. The
++        firmware will disable all access to the peripheral from within the
++        firmware if it finds a DT node using it, and bcm2835-camera will
++        therefore fail to probe.
+         To compile this driver as a module, choose M here. The module will be
+         called bcm2835-unicam.
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * BCM2835 Unicam Capture Driver
++ * BCM283x / BCM271x Unicam Capture Driver
+  *
+  * Copyright (C) 2017-2020 - Raspberry Pi (Trading) Ltd.
+  *
+@@ -554,9 +554,8 @@ static const struct unicam_fmt *find_for
+       return NULL;
+ }
+-static inline unsigned int bytes_per_line(u32 width,
+-                                        const struct unicam_fmt *fmt,
+-                                        u32 v4l2_fourcc)
++static unsigned int bytes_per_line(u32 width, const struct unicam_fmt *fmt,
++                                 u32 v4l2_fourcc)
+ {
+       if (v4l2_fourcc == fmt->repacked_fourcc)
+               /* Repacking always goes to 16bpp */
+@@ -708,7 +707,7 @@ static void unicam_wr_dma_addr(struct un
+       }
+ }
+-static inline unsigned int unicam_get_lines_done(struct unicam_device *dev)
++static unsigned int unicam_get_lines_done(struct unicam_device *dev)
+ {
+       dma_addr_t start_addr, cur_addr;
+       unsigned int stride = dev->node[IMAGE_PAD].v_fmt.fmt.pix.bytesperline;
+@@ -722,7 +721,7 @@ static inline unsigned int unicam_get_li
+       return (unsigned int)(cur_addr - start_addr) / stride;
+ }
+-static inline void unicam_schedule_next_buffer(struct unicam_node *node)
++static void unicam_schedule_next_buffer(struct unicam_node *node)
+ {
+       struct unicam_device *dev = node->dev;
+       struct unicam_buffer *buf;
+@@ -741,7 +740,7 @@ static inline void unicam_schedule_next_
+       unicam_wr_dma_addr(dev, addr, size, node->pad_id);
+ }
+-static inline void unicam_schedule_dummy_buffer(struct unicam_node *node)
++static void unicam_schedule_dummy_buffer(struct unicam_node *node)
+ {
+       struct unicam_device *dev = node->dev;
+@@ -753,8 +752,8 @@ static inline void unicam_schedule_dummy
+       node->next_frm = NULL;
+ }
+-static inline void unicam_process_buffer_complete(struct unicam_node *node,
+-                                                unsigned int sequence)
++static void unicam_process_buffer_complete(struct unicam_node *node,
++                                         unsigned int sequence)
+ {
+       node->cur_frm->vb.field = node->m_fmt.field;
+       node->cur_frm->vb.sequence = sequence;
+@@ -762,16 +761,6 @@ static inline void unicam_process_buffer
+       vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+-static bool unicam_all_nodes_streaming(struct unicam_device *dev)
+-{
+-      bool ret;
+-
+-      ret = dev->node[IMAGE_PAD].open && dev->node[IMAGE_PAD].streaming;
+-      ret &= !dev->node[METADATA_PAD].open ||
+-             dev->node[METADATA_PAD].streaming;
+-      return ret;
+-}
+-
+ static void unicam_queue_event_sof(struct unicam_device *unicam)
+ {
+       struct v4l2_event event = {
+@@ -894,8 +883,8 @@ static int unicam_querycap(struct file *
+       struct unicam_node *node = video_drvdata(file);
+       struct unicam_device *dev = node->dev;
+-      strlcpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
+-      strlcpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
++      strscpy(cap->driver, UNICAM_MODULE_NAME, sizeof(cap->driver));
++      strscpy(cap->card, UNICAM_MODULE_NAME, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                "platform:%s", dev_name(&dev->pdev->dev));
+@@ -988,8 +977,8 @@ static int unicam_g_fmt_vid_cap(struct f
+       return 0;
+ }
+-static
+-const struct unicam_fmt *get_first_supported_format(struct unicam_device *dev)
++static const struct unicam_fmt *
++get_first_supported_format(struct unicam_device *dev)
+ {
+       struct v4l2_subdev_mbus_code_enum mbus_code;
+       const struct unicam_fmt *fmt = NULL;
+@@ -1579,7 +1568,8 @@ static void unicam_disable(struct unicam
+       clk_write(dev, 0);
+ }
+-static void unicam_return_buffers(struct unicam_node *node)
++static void unicam_return_buffers(struct unicam_node *node,
++                                enum vb2_buffer_state state)
+ {
+       struct unicam_buffer *buf, *tmp;
+       unsigned long flags;
+@@ -1587,15 +1577,15 @@ static void unicam_return_buffers(struct
+       spin_lock_irqsave(&node->dma_queue_lock, flags);
+       list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) {
+               list_del(&buf->list);
+-              vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
++              vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
+       if (node->cur_frm)
+               vb2_buffer_done(&node->cur_frm->vb.vb2_buf,
+-                              VB2_BUF_STATE_ERROR);
++                              state);
+       if (node->next_frm && node->cur_frm != node->next_frm)
+               vb2_buffer_done(&node->next_frm->vb.vb2_buf,
+-                              VB2_BUF_STATE_ERROR);
++                              state);
+       node->cur_frm = NULL;
+       node->next_frm = NULL;
+@@ -1612,7 +1602,13 @@ static int unicam_start_streaming(struct
+       int ret;
+       node->streaming = true;
+-      if (!unicam_all_nodes_streaming(dev)) {
++      if (!(dev->node[IMAGE_PAD].open && dev->node[IMAGE_PAD].streaming &&
++            (!dev->node[METADATA_PAD].open ||
++             dev->node[METADATA_PAD].streaming))) {
++              /*
++               * Metadata pad must be enabled before image pad if it is
++               * wanted.
++               */
+               unicam_dbg(3, dev, "Not all nodes are streaming yet.");
+               return 0;
+       }
+@@ -1699,7 +1695,7 @@ err_disable_unicam:
+ err_pm_put:
+       unicam_runtime_put(dev);
+ err_streaming:
+-      unicam_return_buffers(node);
++      unicam_return_buffers(node, VB2_BUF_STATE_QUEUED);
+       node->streaming = false;
+       return ret;
+@@ -1736,7 +1732,7 @@ static void unicam_stop_streaming(struct
+       }
+       /* Clear all queued buffers for the node */
+-      unicam_return_buffers(node);
++      unicam_return_buffers(node, VB2_BUF_STATE_ERROR);
+ }
+ static int unicam_enum_input(struct file *file, void *priv,
+@@ -1754,14 +1750,13 @@ static int unicam_enum_input(struct file
+               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)
++              if (v4l2_subdev_call(dev->sensor, video, g_tvnorms, &inp->std) < 0)
+                       inp->std = V4L2_STD_ALL;
+       } else {
+               inp->capabilities = 0;
+               inp->std = 0;
+       }
+-      sprintf(inp->name, "Camera 0");
++      snprintf(inp->name, sizeof(inp->name), "Camera 0");
+       return 0;
+ }
+@@ -1984,6 +1979,9 @@ static int unicam_s_dv_timings(struct fi
+       ret = v4l2_subdev_call(dev->sensor, video, g_dv_timings,
+                              &current_timings);
++      if (ret < 0)
++              return ret;
++
+       if (v4l2_match_dv_timings(timings, &current_timings, 0, false))
+               return 0;
+@@ -2414,12 +2412,6 @@ static int register_node(struct unicam_d
+               unicam_err(unicam, "Unable to allocate dummy buffer.\n");
+               return -ENOMEM;
+       }
+-
+-      if (pad_id == METADATA_PAD) {
+-              v4l2_disable_ioctl(vdev, VIDIOC_DQEVENT);
+-              v4l2_disable_ioctl(vdev, VIDIOC_SUBSCRIBE_EVENT);
+-              v4l2_disable_ioctl(vdev, VIDIOC_UNSUBSCRIBE_EVENT);
+-      }
+       if (pad_id == METADATA_PAD ||
+           !v4l2_subdev_has_op(unicam->sensor, video, s_std)) {
+               v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_STD);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0811-media-bcm2835-unicam-Retain-packing-information-on-G.patch b/target/linux/bcm27xx/patches-5.4/950-0811-media-bcm2835-unicam-Retain-packing-information-on-G.patch
new file mode 100644 (file)
index 0000000..8d2b9d8
--- /dev/null
@@ -0,0 +1,48 @@
+From bf722c887dd9d0d24493edd20c61b2fcde5f66dd Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 19 May 2020 11:46:47 +0100
+Subject: [PATCH] media: bcm2835-unicam: Retain packing information
+ on G_FMT
+
+The change to retrieve the pixel format always on g_fmt didn't
+check whether the native or unpacked version of the format
+had been requested, and always returned the packed one.
+Correct this so that the packing setting is retained whereever
+possible.
+
+Fixes "9d59e89 media: bcm2835-unicam: Re-fetch mbus code from subdev
+on a g_fmt call"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -970,8 +970,23 @@ static int unicam_g_fmt_vid_cap(struct f
+       if (!fmt)
+               return -EINVAL;
+-      node->fmt = fmt;
+-      node->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++      if (node->fmt != fmt) {
++              /*
++               * The sensor format has changed so the pixelformat needs to
++               * be updated. Try and retain the packed/unpacked choice if
++               * at all possible.
++               */
++              if (node->fmt->repacked_fourcc ==
++                                              node->v_fmt.fmt.pix.pixelformat)
++                      /* Using the repacked format */
++                      node->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
++              else
++                      /* Using the native format */
++                      node->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
++
++              node->fmt = fmt;
++      }
++
+       *f = node->v_fmt;
+       return 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0812-media-bcm2835-unicam-change-minimum-number-of-vb2_qu.patch b/target/linux/bcm27xx/patches-5.4/950-0812-media-bcm2835-unicam-change-minimum-number-of-vb2_qu.patch
new file mode 100644 (file)
index 0000000..770b00b
--- /dev/null
@@ -0,0 +1,28 @@
+From 4f745137c92902f4f541ebe5e458dd2c4e89a42d Mon Sep 17 00:00:00 2001
+From: David Plowman <david.plowman@raspberrypi.com>
+Date: Thu, 28 May 2020 11:09:48 +0100
+Subject: [PATCH] media: bcm2835-unicam: change minimum number of
+ vb2_queue buffers to 1
+
+Since the unicam driver was modified to write to a dummy buffer when no
+user-supplied buffer is available, it can now write to and return a
+buffer even when there's only a single one. Enable this by changing the
+min_buffers_needed in the vb2_queue; it will be useful for enabling
+still captures without allocating more memory than absolutely necessary.
+
+Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -2387,7 +2387,7 @@ static int register_node(struct unicam_d
+       q->buf_struct_size = sizeof(struct unicam_buffer);
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->lock = &node->lock;
+-      q->min_buffers_needed = 2;
++      q->min_buffers_needed = 1;
+       q->dev = &unicam->pdev->dev;
+       ret = vb2_queue_init(q);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0813-dt-dtoverlays-Fix-up-base-DT-and-overlays-for-update.patch b/target/linux/bcm27xx/patches-5.4/950-0813-dt-dtoverlays-Fix-up-base-DT-and-overlays-for-update.patch
new file mode 100644 (file)
index 0000000..edfca1e
--- /dev/null
@@ -0,0 +1,144 @@
+From 7a1905f969cfa2e303f5e74efee56dbd0523e5bb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 23 Jun 2020 15:41:42 +0100
+Subject: [PATCH] dt/dtoverlays: Fix up base DT and overlays for
+ updated Unicam driver
+
+The upstreamed Unicam driver uses a dt property to denote how many
+lanes are supported by the receiver peripheral, independent of
+the number of lanes that the sensor wants to use. It also doesn't
+check the remote endpoint config for the number of lanes as that
+isn't the accepted way of doing things.
+
+Update the base DT for the brcm,num-data-lanes property, and the
+overlays to define the desired number of lanes at both ends of
+the link.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts           |  3 ++-
+ arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi   |  6 +-----
+ arch/arm/boot/dts/bcm283x-rpi-csi1-2lane.dtsi   |  6 +-----
+ arch/arm/boot/dts/bcm283x-rpi-csi1-4lane.dtsi   |  6 +-----
+ arch/arm/boot/dts/overlays/adv7282m-overlay.dts |  1 +
+ arch/arm/boot/dts/overlays/imx477-overlay.dts   |  1 +
+ arch/arm/boot/dts/overlays/irs1125-overlay.dts  |  2 ++
+ arch/arm/boot/dts/overlays/ov5647-overlay.dts   |  1 +
+ arch/arm/boot/dts/overlays/tc358743-overlay.dts | 16 +++++++++++++++-
+ 9 files changed, 25 insertions(+), 17 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -203,7 +203,8 @@
+ };
+ #include "bcm2711-rpi.dtsi"
+-#include "bcm283x-rpi-csi1-2lane.dtsi"
++#include "bcm283x-rpi-csi0-2lane.dtsi"
++#include "bcm283x-rpi-csi1-4lane.dtsi"
+ #include "bcm283x-rpi-i2c0mux_0_44.dtsi"
+ /delete-node/ &emmc2;
+--- a/arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi
++++ b/arch/arm/boot/dts/bcm283x-rpi-csi0-2lane.dtsi
+@@ -1,8 +1,4 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ &csi0 {
+-      port {
+-              endpoint {
+-                      data-lanes = <1 2>;
+-              };
+-      };
++      brcm,num-data-lanes = <2>;
+ };
+--- a/arch/arm/boot/dts/bcm283x-rpi-csi1-2lane.dtsi
++++ b/arch/arm/boot/dts/bcm283x-rpi-csi1-2lane.dtsi
+@@ -1,8 +1,4 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ &csi1 {
+-      port {
+-              endpoint {
+-                      data-lanes = <1 2>;
+-              };
+-      };
++      brcm,num-data-lanes = <2>;
+ };
+--- a/arch/arm/boot/dts/bcm283x-rpi-csi1-4lane.dtsi
++++ b/arch/arm/boot/dts/bcm283x-rpi-csi1-4lane.dtsi
+@@ -1,8 +1,4 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ &csi1 {
+-      port {
+-              endpoint {
+-                      data-lanes = <1 2 3 4>;
+-              };
+-      };
++      brcm,num-data-lanes = <4>;
+ };
+--- a/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adv7282m-overlay.dts
+@@ -40,6 +40,7 @@
+                       port {
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&adv728x_0>;
++                                      data-lanes = <1>;
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/imx477-overlay.dts
++++ b/arch/arm/boot/dts/overlays/imx477-overlay.dts
+@@ -49,6 +49,7 @@
+                       port {
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&imx477_0>;
++                                      data-lanes = <1 2>;
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/irs1125-overlay.dts
++++ b/arch/arm/boot/dts/overlays/irs1125-overlay.dts
+@@ -43,6 +43,8 @@
+                       port {
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&irs1125_0>;
++                                      data-lanes = <1 2>;
++                                      clock-noncontinuous;
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
+@@ -43,6 +43,7 @@
+                       port {
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&ov5647_0>;
++                                      data-lanes = <1 2>;
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts
+@@ -86,8 +86,22 @@
+               };
+       };
++      fragment@7 {
++              target = <&csi1_ep>;
++              __overlay__ {
++                      data-lanes = <1 2>;
++              };
++      };
++
++      fragment@8 {
++              target = <&csi1_ep>;
++              __dormant__ {
++                      data-lanes = <1 2 3 4>;
++              };
++      };
++
+       __overrides__ {
+-              4lane = <0>, "-2+3";
++              4lane = <0>, "-2+3-7+8";
+               link-frequency = <&tc358743>,"link-frequencies#0";
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0814-media-bcm2835-unicam-Avoid-gcc-warning-over-0-on-end.patch b/target/linux/bcm27xx/patches-5.4/950-0814-media-bcm2835-unicam-Avoid-gcc-warning-over-0-on-end.patch
new file mode 100644 (file)
index 0000000..f70dba7
--- /dev/null
@@ -0,0 +1,27 @@
+From 3f8d0137a1fc1cb0333cb99624213fe4622a92b6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 26 Jun 2020 15:53:44 +0100
+Subject: [PATCH] media: bcm2835-unicam: Avoid gcc warning over {0}
+ on endpoint
+
+Older gcc versions object to = { 0 } initialisation if the first
+elemtn in the structure is a substructure.
+
+Use = { } to avoid this compiler warning.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -2578,7 +2578,7 @@ static const struct v4l2_async_notifier_
+ static int of_unicam_connect_subdevs(struct unicam_device *dev)
+ {
+       struct platform_device *pdev = dev->pdev;
+-      struct v4l2_fwnode_endpoint ep = { 0 };
++      struct v4l2_fwnode_endpoint ep = { };
+       struct device_node *ep_node;
+       struct device_node *sensor_node;
+       unsigned int lane;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0815-media-dt-bindings-media-i2c-Add-IMX290-CMOS-sensor-b.patch b/target/linux/bcm27xx/patches-5.4/950-0815-media-dt-bindings-media-i2c-Add-IMX290-CMOS-sensor-b.patch
new file mode 100644 (file)
index 0000000..120ad34
--- /dev/null
@@ -0,0 +1,98 @@
+From 6bbb873c79b9bb0b3ca95fa4a4fe6cfd0ebe9d2c Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 4 Oct 2019 13:05:24 -0300
+Subject: [PATCH] media: dt-bindings: media: i2c: Add IMX290 CMOS
+ sensor binding
+
+Commit 8a97a4676f8b1badcd9cfbed2b081342847bb1b1 upstream.
+
+Add devicetree binding for IMX290 CMOS image sensor. Let's also
+add MAINTAINERS entry for the binding and driver.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ .../devicetree/bindings/media/i2c/imx290.txt  | 57 +++++++++++++++++++
+ MAINTAINERS                                   |  8 +++
+ 2 files changed, 65 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/media/i2c/imx290.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/media/i2c/imx290.txt
+@@ -0,0 +1,57 @@
++* Sony IMX290 1/2.8-Inch CMOS Image Sensor
++
++The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with
++Square Pixel for Color Cameras. It is programmable through I2C and 4-wire
++interfaces. The sensor output is available via CMOS logic parallel SDR output,
++Low voltage LVDS DDR output and CSI-2 serial data output. The CSI-2 bus is the
++default. No bindings have been defined for the other busses.
++
++Required Properties:
++- compatible: Should be "sony,imx290"
++- reg: I2C bus address of the device
++- clocks: Reference to the xclk clock.
++- clock-names: Should be "xclk".
++- clock-frequency: Frequency of the xclk clock in Hz.
++- vdddo-supply: Sensor digital IO regulator.
++- vdda-supply: Sensor analog regulator.
++- vddd-supply: Sensor digital core regulator.
++
++Optional Properties:
++- reset-gpios: Sensor reset GPIO
++
++The imx290 device node should contain one 'port' child node with
++an 'endpoint' subnode. For further reading on port node refer to
++Documentation/devicetree/bindings/media/video-interfaces.txt.
++
++Required Properties on endpoint:
++- data-lanes: check ../video-interfaces.txt
++- link-frequencies: check ../video-interfaces.txt
++- remote-endpoint: check ../video-interfaces.txt
++
++Example:
++      &i2c1 {
++              ...
++              imx290: camera-sensor@1a {
++                      compatible = "sony,imx290";
++                      reg = <0x1a>;
++
++                      reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>;
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&camera_rear_default>;
++
++                      clocks = <&gcc GCC_CAMSS_MCLK0_CLK>;
++                      clock-names = "xclk";
++                      clock-frequency = <37125000>;
++
++                      vdddo-supply = <&camera_vdddo_1v8>;
++                      vdda-supply = <&camera_vdda_2v8>;
++                      vddd-supply = <&camera_vddd_1v5>;
++
++                      port {
++                              imx290_ep: endpoint {
++                                      data-lanes = <1 2 3 4>;
++                                      link-frequencies = /bits/ 64 <445500000>;
++                                      remote-endpoint = <&csiphy0_ep>;
++                              };
++                      };
++              };
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -15200,6 +15200,14 @@ S:    Maintained
+ F:    drivers/media/i2c/imx274.c
+ F:    Documentation/devicetree/bindings/media/i2c/imx274.txt
++SONY IMX290 SENSOR DRIVER
++M:    Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
++L:    linux-media@vger.kernel.org
++T:    git git://linuxtv.org/media_tree.git
++S:    Maintained
++F:    drivers/media/i2c/imx290.c
++F:    Documentation/devicetree/bindings/media/i2c/imx290.txt
++
+ SONY IMX319 SENSOR DRIVER
+ M:    Bingbu Cao <bingbu.cao@intel.com>
+ L:    linux-media@vger.kernel.org
diff --git a/target/linux/bcm27xx/patches-5.4/950-0816-media-i2c-Add-IMX290-CMOS-image-sensor-driver.patch b/target/linux/bcm27xx/patches-5.4/950-0816-media-i2c-Add-IMX290-CMOS-image-sensor-driver.patch
new file mode 100644 (file)
index 0000000..a44aa76
--- /dev/null
@@ -0,0 +1,939 @@
+From d13c94482be9ca356df8a04f8fd5f3738dc31ab1 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 4 Oct 2019 13:05:25 -0300
+Subject: [PATCH] media: i2c: Add IMX290 CMOS image sensor driver
+
+Commit 828dbc299278065b634e913d2700d254a3224853 upstream.
+
+Add driver for Sony IMX290 CMOS image sensor driver. The driver only
+supports I2C interface for programming and MIPI CSI-2 for sensor output.
+
+[Sakari Ailus: Rewrapped a few lines over 80 chars a little.]
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ drivers/media/i2c/Kconfig  |  11 +
+ drivers/media/i2c/Makefile |   1 +
+ drivers/media/i2c/imx290.c | 884 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 896 insertions(+)
+ create mode 100644 drivers/media/i2c/imx290.c
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -609,6 +609,17 @@ config VIDEO_IMX274
+         This is a V4L2 sensor driver for the Sony IMX274
+         CMOS image sensor.
++config VIDEO_IMX290
++      tristate "Sony IMX290 sensor support"
++      depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
++      select V4L2_FWNODE
++      help
++        This is a Video4Linux2 sensor driver for the Sony
++        IMX290 camera sensor.
++
++        To compile this driver as a module, choose M here: the
++        module will be called imx290.
++
+ config VIDEO_IMX477
+       tristate "Sony IMX477 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+--- a/drivers/media/i2c/Makefile
++++ b/drivers/media/i2c/Makefile
+@@ -114,6 +114,7 @@ obj-$(CONFIG_VIDEO_IMX214) += imx214.o
+ obj-$(CONFIG_VIDEO_IMX219)    += imx219.o
+ obj-$(CONFIG_VIDEO_IMX258)    += imx258.o
+ obj-$(CONFIG_VIDEO_IMX274)    += imx274.o
++obj-$(CONFIG_VIDEO_IMX290)    += imx290.o
+ obj-$(CONFIG_VIDEO_IMX477)    += imx477.o
+ obj-$(CONFIG_VIDEO_IMX319)    += imx319.o
+ obj-$(CONFIG_VIDEO_IMX355)    += imx355.o
+--- /dev/null
++++ b/drivers/media/i2c/imx290.c
+@@ -0,0 +1,884 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Sony IMX290 CMOS Image Sensor Driver
++ *
++ * Copyright (C) 2019 FRAMOS GmbH.
++ *
++ * Copyright (C) 2019 Linaro Ltd.
++ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/gpio/consumer.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/pm_runtime.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <media/media-entity.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-fwnode.h>
++#include <media/v4l2-subdev.h>
++
++#define IMX290_STANDBY 0x3000
++#define IMX290_REGHOLD 0x3001
++#define IMX290_XMSTA 0x3002
++#define IMX290_GAIN 0x3014
++
++#define IMX290_DEFAULT_LINK_FREQ 445500000
++
++static const char * const imx290_supply_name[] = {
++      "vdda",
++      "vddd",
++      "vdddo",
++};
++
++#define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
++
++struct imx290_regval {
++      u16 reg;
++      u8 val;
++};
++
++struct imx290_mode {
++      u32 width;
++      u32 height;
++      u32 pixel_rate;
++      u32 link_freq_index;
++
++      const struct imx290_regval *data;
++      u32 data_size;
++};
++
++struct imx290 {
++      struct device *dev;
++      struct clk *xclk;
++      struct regmap *regmap;
++
++      struct v4l2_subdev sd;
++      struct v4l2_fwnode_endpoint ep;
++      struct media_pad pad;
++      struct v4l2_mbus_framefmt current_format;
++      const struct imx290_mode *current_mode;
++
++      struct regulator_bulk_data supplies[IMX290_NUM_SUPPLIES];
++      struct gpio_desc *rst_gpio;
++
++      struct v4l2_ctrl_handler ctrls;
++      struct v4l2_ctrl *link_freq;
++      struct v4l2_ctrl *pixel_rate;
++
++      struct mutex lock;
++};
++
++struct imx290_pixfmt {
++      u32 code;
++};
++
++static const struct imx290_pixfmt imx290_formats[] = {
++      { MEDIA_BUS_FMT_SRGGB10_1X10 },
++};
++
++static const struct regmap_config imx290_regmap_config = {
++      .reg_bits = 16,
++      .val_bits = 8,
++      .cache_type = REGCACHE_RBTREE,
++};
++
++static const struct imx290_regval imx290_global_init_settings[] = {
++      { 0x3007, 0x00 },
++      { 0x3009, 0x00 },
++      { 0x3018, 0x65 },
++      { 0x3019, 0x04 },
++      { 0x301a, 0x00 },
++      { 0x3443, 0x03 },
++      { 0x3444, 0x20 },
++      { 0x3445, 0x25 },
++      { 0x3407, 0x03 },
++      { 0x303a, 0x0c },
++      { 0x3040, 0x00 },
++      { 0x3041, 0x00 },
++      { 0x303c, 0x00 },
++      { 0x303d, 0x00 },
++      { 0x3042, 0x9c },
++      { 0x3043, 0x07 },
++      { 0x303e, 0x49 },
++      { 0x303f, 0x04 },
++      { 0x304b, 0x0a },
++      { 0x300f, 0x00 },
++      { 0x3010, 0x21 },
++      { 0x3012, 0x64 },
++      { 0x3016, 0x09 },
++      { 0x3070, 0x02 },
++      { 0x3071, 0x11 },
++      { 0x309b, 0x10 },
++      { 0x309c, 0x22 },
++      { 0x30a2, 0x02 },
++      { 0x30a6, 0x20 },
++      { 0x30a8, 0x20 },
++      { 0x30aa, 0x20 },
++      { 0x30ac, 0x20 },
++      { 0x30b0, 0x43 },
++      { 0x3119, 0x9e },
++      { 0x311c, 0x1e },
++      { 0x311e, 0x08 },
++      { 0x3128, 0x05 },
++      { 0x313d, 0x83 },
++      { 0x3150, 0x03 },
++      { 0x317e, 0x00 },
++      { 0x32b8, 0x50 },
++      { 0x32b9, 0x10 },
++      { 0x32ba, 0x00 },
++      { 0x32bb, 0x04 },
++      { 0x32c8, 0x50 },
++      { 0x32c9, 0x10 },
++      { 0x32ca, 0x00 },
++      { 0x32cb, 0x04 },
++      { 0x332c, 0xd3 },
++      { 0x332d, 0x10 },
++      { 0x332e, 0x0d },
++      { 0x3358, 0x06 },
++      { 0x3359, 0xe1 },
++      { 0x335a, 0x11 },
++      { 0x3360, 0x1e },
++      { 0x3361, 0x61 },
++      { 0x3362, 0x10 },
++      { 0x33b0, 0x50 },
++      { 0x33b2, 0x1a },
++      { 0x33b3, 0x04 },
++};
++
++static const struct imx290_regval imx290_1080p_settings[] = {
++      /* mode settings */
++      { 0x3007, 0x00 },
++      { 0x303a, 0x0c },
++      { 0x3414, 0x0a },
++      { 0x3472, 0x80 },
++      { 0x3473, 0x07 },
++      { 0x3418, 0x38 },
++      { 0x3419, 0x04 },
++      { 0x3012, 0x64 },
++      { 0x3013, 0x00 },
++      { 0x305c, 0x18 },
++      { 0x305d, 0x03 },
++      { 0x305e, 0x20 },
++      { 0x305f, 0x01 },
++      { 0x315e, 0x1a },
++      { 0x3164, 0x1a },
++      { 0x3480, 0x49 },
++      /* data rate settings */
++      { 0x3009, 0x01 },
++      { 0x3405, 0x10 },
++      { 0x3446, 0x57 },
++      { 0x3447, 0x00 },
++      { 0x3448, 0x37 },
++      { 0x3449, 0x00 },
++      { 0x344a, 0x1f },
++      { 0x344b, 0x00 },
++      { 0x344c, 0x1f },
++      { 0x344d, 0x00 },
++      { 0x344e, 0x1f },
++      { 0x344f, 0x00 },
++      { 0x3450, 0x77 },
++      { 0x3451, 0x00 },
++      { 0x3452, 0x1f },
++      { 0x3453, 0x00 },
++      { 0x3454, 0x17 },
++      { 0x3455, 0x00 },
++      { 0x301c, 0x98 },
++      { 0x301d, 0x08 },
++};
++
++static const struct imx290_regval imx290_720p_settings[] = {
++      /* mode settings */
++      { 0x3007, 0x10 },
++      { 0x303a, 0x06 },
++      { 0x3414, 0x04 },
++      { 0x3472, 0x00 },
++      { 0x3473, 0x05 },
++      { 0x3418, 0xd0 },
++      { 0x3419, 0x02 },
++      { 0x3012, 0x64 },
++      { 0x3013, 0x00 },
++      { 0x305c, 0x20 },
++      { 0x305d, 0x00 },
++      { 0x305e, 0x20 },
++      { 0x305f, 0x01 },
++      { 0x315e, 0x1a },
++      { 0x3164, 0x1a },
++      { 0x3480, 0x49 },
++      /* data rate settings */
++      { 0x3009, 0x01 },
++      { 0x3405, 0x10 },
++      { 0x3446, 0x4f },
++      { 0x3447, 0x00 },
++      { 0x3448, 0x2f },
++      { 0x3449, 0x00 },
++      { 0x344a, 0x17 },
++      { 0x344b, 0x00 },
++      { 0x344c, 0x17 },
++      { 0x344d, 0x00 },
++      { 0x344e, 0x17 },
++      { 0x344f, 0x00 },
++      { 0x3450, 0x57 },
++      { 0x3451, 0x00 },
++      { 0x3452, 0x17 },
++      { 0x3453, 0x00 },
++      { 0x3454, 0x17 },
++      { 0x3455, 0x00 },
++      { 0x301c, 0xe4 },
++      { 0x301d, 0x0c },
++};
++
++static const struct imx290_regval imx290_10bit_settings[] = {
++      { 0x3005, 0x00},
++      { 0x3046, 0x00},
++      { 0x3129, 0x1d},
++      { 0x317c, 0x12},
++      { 0x31ec, 0x37},
++      { 0x3441, 0x0a},
++      { 0x3442, 0x0a},
++      { 0x300a, 0x3c},
++      { 0x300b, 0x00},
++};
++
++/* supported link frequencies */
++static const s64 imx290_link_freq[] = {
++      IMX290_DEFAULT_LINK_FREQ,
++};
++
++/* Mode configs */
++static const struct imx290_mode imx290_modes[] = {
++      {
++              .width = 1920,
++              .height = 1080,
++              .data = imx290_1080p_settings,
++              .data_size = ARRAY_SIZE(imx290_1080p_settings),
++              .pixel_rate = 178200000,
++              .link_freq_index = 0,
++      },
++      {
++              .width = 1280,
++              .height = 720,
++              .data = imx290_720p_settings,
++              .data_size = ARRAY_SIZE(imx290_720p_settings),
++              .pixel_rate = 178200000,
++              .link_freq_index = 0,
++      },
++};
++
++static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
++{
++      return container_of(_sd, struct imx290, sd);
++}
++
++static inline int imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value)
++{
++      unsigned int regval;
++      int ret;
++
++      ret = regmap_read(imx290->regmap, addr, &regval);
++      if (ret) {
++              dev_err(imx290->dev, "I2C read failed for addr: %x\n", addr);
++              return ret;
++      }
++
++      *value = regval & 0xff;
++
++      return 0;
++}
++
++static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
++{
++      int ret;
++
++      ret = regmap_write(imx290->regmap, addr, value);
++      if (ret) {
++              dev_err(imx290->dev, "I2C write failed for addr: %x\n", addr);
++              return ret;
++      }
++
++      return ret;
++}
++
++static int imx290_set_register_array(struct imx290 *imx290,
++                                   const struct imx290_regval *settings,
++                                   unsigned int num_settings)
++{
++      unsigned int i;
++      int ret;
++
++      for (i = 0; i < num_settings; ++i, ++settings) {
++              ret = imx290_write_reg(imx290, settings->reg, settings->val);
++              if (ret < 0)
++                      return ret;
++
++              /* Settle time is 10ms for all registers */
++              msleep(10);
++      }
++
++      return 0;
++}
++
++static int imx290_write_buffered_reg(struct imx290 *imx290, u16 address_low,
++                                   u8 nr_regs, u32 value)
++{
++      unsigned int i;
++      int ret;
++
++      ret = imx290_write_reg(imx290, IMX290_REGHOLD, 0x01);
++      if (ret) {
++              dev_err(imx290->dev, "Error setting hold register\n");
++              return ret;
++      }
++
++      for (i = 0; i < nr_regs; i++) {
++              ret = imx290_write_reg(imx290, address_low + i,
++                                     (u8)(value >> (i * 8)));
++              if (ret) {
++                      dev_err(imx290->dev, "Error writing buffered registers\n");
++                      return ret;
++              }
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_REGHOLD, 0x00);
++      if (ret) {
++              dev_err(imx290->dev, "Error setting hold register\n");
++              return ret;
++      }
++
++      return ret;
++}
++
++static int imx290_set_gain(struct imx290 *imx290, u32 value)
++{
++      int ret;
++
++      ret = imx290_write_buffered_reg(imx290, IMX290_GAIN, 1, value);
++      if (ret)
++              dev_err(imx290->dev, "Unable to write gain\n");
++
++      return ret;
++}
++
++/* Stop streaming */
++static int imx290_stop_streaming(struct imx290 *imx290)
++{
++      int ret;
++
++      ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x01);
++      if (ret < 0)
++              return ret;
++
++      msleep(30);
++
++      return imx290_write_reg(imx290, IMX290_XMSTA, 0x01);
++}
++
++static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
++{
++      struct imx290 *imx290 = container_of(ctrl->handler,
++                                           struct imx290, ctrls);
++      int ret = 0;
++
++      /* V4L2 controls values will be applied only when power is already up */
++      if (!pm_runtime_get_if_in_use(imx290->dev))
++              return 0;
++
++      switch (ctrl->id) {
++      case V4L2_CID_GAIN:
++              ret = imx290_set_gain(imx290, ctrl->val);
++              break;
++      default:
++              ret = -EINVAL;
++              break;
++      }
++
++      pm_runtime_put(imx290->dev);
++
++      return ret;
++}
++
++static const struct v4l2_ctrl_ops imx290_ctrl_ops = {
++      .s_ctrl = imx290_set_ctrl,
++};
++
++static int imx290_enum_mbus_code(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_pad_config *cfg,
++                               struct v4l2_subdev_mbus_code_enum *code)
++{
++      if (code->index >= ARRAY_SIZE(imx290_formats))
++              return -EINVAL;
++
++      code->code = imx290_formats[code->index].code;
++
++      return 0;
++}
++
++static int imx290_get_fmt(struct v4l2_subdev *sd,
++                        struct v4l2_subdev_pad_config *cfg,
++                        struct v4l2_subdev_format *fmt)
++{
++      struct imx290 *imx290 = to_imx290(sd);
++      struct v4l2_mbus_framefmt *framefmt;
++
++      mutex_lock(&imx290->lock);
++
++      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
++              framefmt = v4l2_subdev_get_try_format(&imx290->sd, cfg,
++                                                    fmt->pad);
++      else
++              framefmt = &imx290->current_format;
++
++      fmt->format = *framefmt;
++
++      mutex_unlock(&imx290->lock);
++
++      return 0;
++}
++
++static int imx290_set_fmt(struct v4l2_subdev *sd,
++                        struct v4l2_subdev_pad_config *cfg,
++                    struct v4l2_subdev_format *fmt)
++{
++      struct imx290 *imx290 = to_imx290(sd);
++      const struct imx290_mode *mode;
++      struct v4l2_mbus_framefmt *format;
++      unsigned int i;
++
++      mutex_lock(&imx290->lock);
++
++      mode = v4l2_find_nearest_size(imx290_modes,
++                                    ARRAY_SIZE(imx290_modes),
++                                    width, height,
++                                    fmt->format.width, fmt->format.height);
++
++      fmt->format.width = mode->width;
++      fmt->format.height = mode->height;
++
++      for (i = 0; i < ARRAY_SIZE(imx290_formats); i++)
++              if (imx290_formats[i].code == fmt->format.code)
++                      break;
++
++      if (i >= ARRAY_SIZE(imx290_formats))
++              i = 0;
++
++      fmt->format.code = imx290_formats[i].code;
++      fmt->format.field = V4L2_FIELD_NONE;
++
++      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
++              format = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
++      } else {
++              format = &imx290->current_format;
++              __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
++              __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, mode->pixel_rate);
++
++              imx290->current_mode = mode;
++      }
++
++      *format = fmt->format;
++
++      mutex_unlock(&imx290->lock);
++
++      return 0;
++}
++
++static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
++                                struct v4l2_subdev_pad_config *cfg)
++{
++      struct v4l2_subdev_format fmt = { 0 };
++
++      fmt.which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
++      fmt.format.width = 1920;
++      fmt.format.height = 1080;
++
++      imx290_set_fmt(subdev, cfg, &fmt);
++
++      return 0;
++}
++
++static int imx290_write_current_format(struct imx290 *imx290,
++                                     struct v4l2_mbus_framefmt *format)
++{
++      int ret;
++
++      switch (format->code) {
++      case MEDIA_BUS_FMT_SRGGB10_1X10:
++              ret = imx290_set_register_array(imx290, imx290_10bit_settings,
++                                              ARRAY_SIZE(
++                                                      imx290_10bit_settings));
++              if (ret < 0) {
++                      dev_err(imx290->dev, "Could not set format registers\n");
++                      return ret;
++              }
++              break;
++      default:
++              dev_err(imx290->dev, "Unknown pixel format\n");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++/* Start streaming */
++static int imx290_start_streaming(struct imx290 *imx290)
++{
++      int ret;
++
++      /* Set init register settings */
++      ret = imx290_set_register_array(imx290, imx290_global_init_settings,
++                                      ARRAY_SIZE(
++                                              imx290_global_init_settings));
++      if (ret < 0) {
++              dev_err(imx290->dev, "Could not set init registers\n");
++              return ret;
++      }
++
++      /* Set current frame format */
++      ret = imx290_write_current_format(imx290, &imx290->current_format);
++      if (ret < 0) {
++              dev_err(imx290->dev, "Could not set frame format\n");
++              return ret;
++      }
++
++      /* Apply default values of current mode */
++      ret = imx290_set_register_array(imx290, imx290->current_mode->data,
++                                      imx290->current_mode->data_size);
++      if (ret < 0) {
++              dev_err(imx290->dev, "Could not set current mode\n");
++              return ret;
++      }
++
++      /* Apply customized values from user */
++      ret = v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
++      if (ret) {
++              dev_err(imx290->dev, "Could not sync v4l2 controls\n");
++              return ret;
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x00);
++      if (ret < 0)
++              return ret;
++
++      msleep(30);
++
++      /* Start streaming */
++      return imx290_write_reg(imx290, IMX290_XMSTA, 0x00);
++}
++
++static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
++{
++      struct imx290 *imx290 = to_imx290(sd);
++      int ret = 0;
++
++      if (enable) {
++              ret = pm_runtime_get_sync(imx290->dev);
++              if (ret < 0) {
++                      pm_runtime_put_noidle(imx290->dev);
++                      goto unlock_and_return;
++              }
++
++              ret = imx290_start_streaming(imx290);
++              if (ret) {
++                      dev_err(imx290->dev, "Start stream failed\n");
++                      pm_runtime_put(imx290->dev);
++                      goto unlock_and_return;
++              }
++      } else {
++              imx290_stop_streaming(imx290);
++              pm_runtime_put(imx290->dev);
++      }
++
++unlock_and_return:
++
++      return ret;
++}
++
++static int imx290_get_regulators(struct device *dev, struct imx290 *imx290)
++{
++      unsigned int i;
++
++      for (i = 0; i < IMX290_NUM_SUPPLIES; i++)
++              imx290->supplies[i].supply = imx290_supply_name[i];
++
++      return devm_regulator_bulk_get(dev, IMX290_NUM_SUPPLIES,
++                                     imx290->supplies);
++}
++
++static int imx290_power_on(struct device *dev)
++{
++      struct i2c_client *client = to_i2c_client(dev);
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct imx290 *imx290 = to_imx290(sd);
++      int ret;
++
++      ret = clk_prepare_enable(imx290->xclk);
++      if (ret) {
++              dev_err(imx290->dev, "Failed to enable clock\n");
++              return ret;
++      }
++
++      ret = regulator_bulk_enable(IMX290_NUM_SUPPLIES, imx290->supplies);
++      if (ret) {
++              dev_err(imx290->dev, "Failed to enable regulators\n");
++              clk_disable_unprepare(imx290->xclk);
++              return ret;
++      }
++
++      usleep_range(1, 2);
++      gpiod_set_value_cansleep(imx290->rst_gpio, 1);
++      usleep_range(30000, 31000);
++
++      return 0;
++}
++
++static int imx290_power_off(struct device *dev)
++{
++      struct i2c_client *client = to_i2c_client(dev);
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct imx290 *imx290 = to_imx290(sd);
++
++      clk_disable_unprepare(imx290->xclk);
++      gpiod_set_value_cansleep(imx290->rst_gpio, 0);
++      regulator_bulk_disable(IMX290_NUM_SUPPLIES, imx290->supplies);
++
++      return 0;
++}
++
++static const struct dev_pm_ops imx290_pm_ops = {
++      SET_RUNTIME_PM_OPS(imx290_power_on, imx290_power_off, NULL)
++};
++
++static const struct v4l2_subdev_video_ops imx290_video_ops = {
++      .s_stream = imx290_set_stream,
++};
++
++static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
++      .init_cfg = imx290_entity_init_cfg,
++      .enum_mbus_code = imx290_enum_mbus_code,
++      .get_fmt = imx290_get_fmt,
++      .set_fmt = imx290_set_fmt,
++};
++
++static const struct v4l2_subdev_ops imx290_subdev_ops = {
++      .video = &imx290_video_ops,
++      .pad = &imx290_pad_ops,
++};
++
++static const struct media_entity_operations imx290_subdev_entity_ops = {
++      .link_validate = v4l2_subdev_link_validate,
++};
++
++static int imx290_probe(struct i2c_client *client)
++{
++      struct device *dev = &client->dev;
++      struct fwnode_handle *endpoint;
++      struct imx290 *imx290;
++      u32 xclk_freq;
++      int ret;
++
++      imx290 = devm_kzalloc(dev, sizeof(*imx290), GFP_KERNEL);
++      if (!imx290)
++              return -ENOMEM;
++
++      imx290->dev = dev;
++      imx290->regmap = devm_regmap_init_i2c(client, &imx290_regmap_config);
++      if (IS_ERR(imx290->regmap)) {
++              dev_err(dev, "Unable to initialize I2C\n");
++              return -ENODEV;
++      }
++
++      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
++      if (!endpoint) {
++              dev_err(dev, "Endpoint node not found\n");
++              return -EINVAL;
++      }
++
++      ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &imx290->ep);
++      fwnode_handle_put(endpoint);
++      if (ret) {
++              dev_err(dev, "Parsing endpoint node failed\n");
++              goto free_err;
++      }
++
++      if (!imx290->ep.nr_of_link_frequencies) {
++              dev_err(dev, "link-frequency property not found in DT\n");
++              ret = -EINVAL;
++              goto free_err;
++      }
++
++      if (imx290->ep.link_frequencies[0] != IMX290_DEFAULT_LINK_FREQ) {
++              dev_err(dev, "Unsupported link frequency\n");
++              ret = -EINVAL;
++              goto free_err;
++      }
++
++      /* Only CSI2 is supported for now */
++      if (imx290->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
++              dev_err(dev, "Unsupported bus type, should be CSI2\n");
++              ret = -EINVAL;
++              goto free_err;
++      }
++
++      /* Set default mode to max resolution */
++      imx290->current_mode = &imx290_modes[0];
++
++      /* get system clock (xclk) */
++      imx290->xclk = devm_clk_get(dev, "xclk");
++      if (IS_ERR(imx290->xclk)) {
++              dev_err(dev, "Could not get xclk");
++              ret = PTR_ERR(imx290->xclk);
++              goto free_err;
++      }
++
++      ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
++                                     &xclk_freq);
++      if (ret) {
++              dev_err(dev, "Could not get xclk frequency\n");
++              goto free_err;
++      }
++
++      /* external clock must be 37.125 MHz */
++      if (xclk_freq != 37125000) {
++              dev_err(dev, "External clock frequency %u is not supported\n",
++                      xclk_freq);
++              ret = -EINVAL;
++              goto free_err;
++      }
++
++      ret = clk_set_rate(imx290->xclk, xclk_freq);
++      if (ret) {
++              dev_err(dev, "Could not set xclk frequency\n");
++              goto free_err;
++      }
++
++      ret = imx290_get_regulators(dev, imx290);
++      if (ret < 0) {
++              dev_err(dev, "Cannot get regulators\n");
++              goto free_err;
++      }
++
++      imx290->rst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
++      if (IS_ERR(imx290->rst_gpio)) {
++              dev_err(dev, "Cannot get reset gpio\n");
++              ret = PTR_ERR(imx290->rst_gpio);
++              goto free_err;
++      }
++
++      mutex_init(&imx290->lock);
++
++      v4l2_ctrl_handler_init(&imx290->ctrls, 3);
++
++      v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                        V4L2_CID_GAIN, 0, 72, 1, 0);
++      imx290->link_freq =
++              v4l2_ctrl_new_int_menu(&imx290->ctrls,
++                                     &imx290_ctrl_ops,
++                                     V4L2_CID_LINK_FREQ,
++                                     ARRAY_SIZE(imx290_link_freq) - 1,
++                                     0, imx290_link_freq);
++      if (imx290->link_freq)
++              imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++
++      imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                                             V4L2_CID_PIXEL_RATE, 1,
++                                             INT_MAX, 1,
++                                             imx290_modes[0].pixel_rate);
++
++      imx290->sd.ctrl_handler = &imx290->ctrls;
++
++      if (imx290->ctrls.error) {
++              dev_err(dev, "Control initialization error %d\n",
++                      imx290->ctrls.error);
++              ret = imx290->ctrls.error;
++              goto free_ctrl;
++      }
++
++      v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
++      imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
++      imx290->sd.dev = &client->dev;
++      imx290->sd.entity.ops = &imx290_subdev_entity_ops;
++      imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
++
++      imx290->pad.flags = MEDIA_PAD_FL_SOURCE;
++      ret = media_entity_pads_init(&imx290->sd.entity, 1, &imx290->pad);
++      if (ret < 0) {
++              dev_err(dev, "Could not register media entity\n");
++              goto free_ctrl;
++      }
++
++      ret = v4l2_async_register_subdev(&imx290->sd);
++      if (ret < 0) {
++              dev_err(dev, "Could not register v4l2 device\n");
++              goto free_entity;
++      }
++
++      /* Power on the device to match runtime PM state below */
++      ret = imx290_power_on(dev);
++      if (ret < 0) {
++              dev_err(dev, "Could not power on the device\n");
++              goto free_entity;
++      }
++
++      pm_runtime_set_active(dev);
++      pm_runtime_enable(dev);
++      pm_runtime_idle(dev);
++
++      v4l2_fwnode_endpoint_free(&imx290->ep);
++
++      return 0;
++
++free_entity:
++      media_entity_cleanup(&imx290->sd.entity);
++free_ctrl:
++      v4l2_ctrl_handler_free(&imx290->ctrls);
++      mutex_destroy(&imx290->lock);
++free_err:
++      v4l2_fwnode_endpoint_free(&imx290->ep);
++
++      return ret;
++}
++
++static int imx290_remove(struct i2c_client *client)
++{
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct imx290 *imx290 = to_imx290(sd);
++
++      v4l2_async_unregister_subdev(sd);
++      media_entity_cleanup(&sd->entity);
++      v4l2_ctrl_handler_free(sd->ctrl_handler);
++
++      mutex_destroy(&imx290->lock);
++
++      pm_runtime_disable(imx290->dev);
++      if (!pm_runtime_status_suspended(imx290->dev))
++              imx290_power_off(imx290->dev);
++      pm_runtime_set_suspended(imx290->dev);
++
++      return 0;
++}
++
++static const struct of_device_id imx290_of_match[] = {
++      { .compatible = "sony,imx290" },
++      { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, imx290_of_match);
++
++static struct i2c_driver imx290_i2c_driver = {
++      .probe_new  = imx290_probe,
++      .remove = imx290_remove,
++      .driver = {
++              .name  = "imx290",
++              .pm = &imx290_pm_ops,
++              .of_match_table = of_match_ptr(imx290_of_match),
++      },
++};
++
++module_i2c_driver(imx290_i2c_driver);
++
++MODULE_DESCRIPTION("Sony IMX290 CMOS Image Sensor Driver");
++MODULE_AUTHOR("FRAMOS GmbH");
++MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0817-media-i2c-imx290-set-the-format-before-VIDIOC_SUBDEV.patch b/target/linux/bcm27xx/patches-5.4/950-0817-media-i2c-imx290-set-the-format-before-VIDIOC_SUBDEV.patch
new file mode 100644 (file)
index 0000000..68f8fcf
--- /dev/null
@@ -0,0 +1,50 @@
+From 2beb8ff8039f3ee8262f05d7f3d91c44826e5df9 Mon Sep 17 00:00:00 2001
+From: Andrey Konovalov <andrey.konovalov@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:46 +0200
+Subject: [PATCH] media: i2c: imx290: set the format before
+ VIDIOC_SUBDEV_G_FMT is called
+
+Commit d46cfdc86c30d5ec768924f0b1e2683c8d20b671 upstream.
+
+With the current driver 'media-ctl -p' issued right after the imx290 driver
+is loaded prints:
+pad0: Source
+             [fmt:unknown/0x0]
+
+The format value of zero is due to the current_format field of the imx290
+struct not being initialized yet.
+
+As imx290_entity_init_cfg() calls imx290_set_fmt(), the current_mode field
+is also initialized, so the line which set current_mode to a default value
+in driver's probe() function is no longer needed.
+
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -722,9 +722,6 @@ static int imx290_probe(struct i2c_clien
+               goto free_err;
+       }
+-      /* Set default mode to max resolution */
+-      imx290->current_mode = &imx290_modes[0];
+-
+       /* get system clock (xclk) */
+       imx290->xclk = devm_clk_get(dev, "xclk");
+       if (IS_ERR(imx290->xclk)) {
+@@ -809,6 +806,9 @@ static int imx290_probe(struct i2c_clien
+               goto free_ctrl;
+       }
++      /* Initialize the frame format (this also sets imx290->current_mode) */
++      imx290_entity_init_cfg(&imx290->sd, NULL);
++
+       ret = v4l2_async_register_subdev(&imx290->sd);
+       if (ret < 0) {
+               dev_err(dev, "Could not register v4l2 device\n");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0818-media-i2c-imx290-fix-the-order-of-the-args-in-SET_RU.patch b/target/linux/bcm27xx/patches-5.4/950-0818-media-i2c-imx290-fix-the-order-of-the-args-in-SET_RU.patch
new file mode 100644 (file)
index 0000000..a3332a7
--- /dev/null
@@ -0,0 +1,30 @@
+From 8c3334dd193798648c329779ce7a3c6ddec7944e Mon Sep 17 00:00:00 2001
+From: Andrey Konovalov <andrey.konovalov@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:47 +0200
+Subject: [PATCH] media: i2c: imx290: fix the order of the args in
+ SET_RUNTIME_PM_OPS()
+
+Commit 8d2d1bedb1b9af3e0c039a4444858da7b6da71f8 upstream.
+
+The macro is defined as SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn),
+so imx290_power_off must be the 1st arg, and imx290_power_on the 2nd.
+
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -648,7 +648,7 @@ static int imx290_power_off(struct devic
+ }
+ static const struct dev_pm_ops imx290_pm_ops = {
+-      SET_RUNTIME_PM_OPS(imx290_power_on, imx290_power_off, NULL)
++      SET_RUNTIME_PM_OPS(imx290_power_off, imx290_power_on, NULL)
+ };
+ static const struct v4l2_subdev_video_ops imx290_video_ops = {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0819-media-i2c-imx290-fix-reset-GPIO-pin-handling.patch b/target/linux/bcm27xx/patches-5.4/950-0819-media-i2c-imx290-fix-reset-GPIO-pin-handling.patch
new file mode 100644 (file)
index 0000000..f4c122d
--- /dev/null
@@ -0,0 +1,61 @@
+From 47f49370b3c1c7f4d4aae855966d2a3beef6c6d4 Mon Sep 17 00:00:00 2001
+From: Andrey Konovalov <andrey.konovalov@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:48 +0200
+Subject: [PATCH] media: i2c: imx290: fix reset GPIO pin handling
+
+Commit 3909a92d7df622b41b9ceeeea694e641cad7667b upstream.
+
+According to https://www.kernel.org/doc/Documentation/gpio/consumer.txt,
+
+- all of the gpiod_set_value_xxx() functions operate with the *logical*
+value. So in imx290_power_on() the reset signal should be cleared
+(de-asserted) with gpiod_set_value_cansleep(imx290->rst_gpio, 0), and in
+imx290_power_off() the value of 1 must be used to apply/assert the reset
+to the sensor. In the device tree the reset pin is described as
+GPIO_ACTIVE_LOW, and gpiod_set_value_xxx() functions take this into
+account,
+
+- when devm_gpiod_get_optional() is called with GPIOD_ASIS, the GPIO is
+not initialized, and the direction must be set later; using a GPIO
+without setting its direction first is illegal and will result in undefined
+behavior. Fix this by using GPIOD_OUT_HIGH instead of GPIOD_ASIS (this
+asserts the reset signal to the sensor initially).
+
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -628,7 +628,7 @@ static int imx290_power_on(struct device
+       }
+       usleep_range(1, 2);
+-      gpiod_set_value_cansleep(imx290->rst_gpio, 1);
++      gpiod_set_value_cansleep(imx290->rst_gpio, 0);
+       usleep_range(30000, 31000);
+       return 0;
+@@ -641,7 +641,7 @@ static int imx290_power_off(struct devic
+       struct imx290 *imx290 = to_imx290(sd);
+       clk_disable_unprepare(imx290->xclk);
+-      gpiod_set_value_cansleep(imx290->rst_gpio, 0);
++      gpiod_set_value_cansleep(imx290->rst_gpio, 1);
+       regulator_bulk_disable(IMX290_NUM_SUPPLIES, imx290->supplies);
+       return 0;
+@@ -757,7 +757,8 @@ static int imx290_probe(struct i2c_clien
+               goto free_err;
+       }
+-      imx290->rst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
++      imx290->rst_gpio = devm_gpiod_get_optional(dev, "reset",
++                                                 GPIOD_OUT_HIGH);
+       if (IS_ERR(imx290->rst_gpio)) {
+               dev_err(dev, "Cannot get reset gpio\n");
+               ret = PTR_ERR(imx290->rst_gpio);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0820-media-i2c-imx290-Add-support-for-2-data-lanes.patch b/target/linux/bcm27xx/patches-5.4/950-0820-media-i2c-imx290-Add-support-for-2-data-lanes.patch
new file mode 100644 (file)
index 0000000..68b8999
--- /dev/null
@@ -0,0 +1,314 @@
+From 78d867300b5026ab31c9a3fbd37b6590b7940f66 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:49 +0200
+Subject: [PATCH] media: i2c: imx290: Add support for 2 data lanes
+
+Commit 97589ad61c730e0f486635c6c19fa25ab8e8f29d upstream.
+
+The IMX290 sensor can output frames with 2/4 CSI2 data lanes. This commit
+adds support for 2 lane mode in addition to the 4 lane and also
+configuring the data lane settings in the driver based on system
+configuration.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 147 +++++++++++++++++++++++++++++++++----
+ 1 file changed, 133 insertions(+), 14 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -25,7 +25,12 @@
+ #define IMX290_STANDBY 0x3000
+ #define IMX290_REGHOLD 0x3001
+ #define IMX290_XMSTA 0x3002
++#define IMX290_FR_FDG_SEL 0x3009
+ #define IMX290_GAIN 0x3014
++#define IMX290_HMAX_LOW 0x301c
++#define IMX290_HMAX_HIGH 0x301d
++#define IMX290_PHY_LANE_NUM 0x3407
++#define IMX290_CSI_LANE_MODE 0x3443
+ #define IMX290_DEFAULT_LINK_FREQ 445500000
+@@ -45,6 +50,7 @@ struct imx290_regval {
+ struct imx290_mode {
+       u32 width;
+       u32 height;
++      u32 hmax;
+       u32 pixel_rate;
+       u32 link_freq_index;
+@@ -56,6 +62,7 @@ struct imx290 {
+       struct device *dev;
+       struct clk *xclk;
+       struct regmap *regmap;
++      u8 nlanes;
+       struct v4l2_subdev sd;
+       struct v4l2_fwnode_endpoint ep;
+@@ -89,14 +96,11 @@ static const struct regmap_config imx290
+ static const struct imx290_regval imx290_global_init_settings[] = {
+       { 0x3007, 0x00 },
+-      { 0x3009, 0x00 },
+       { 0x3018, 0x65 },
+       { 0x3019, 0x04 },
+       { 0x301a, 0x00 },
+-      { 0x3443, 0x03 },
+       { 0x3444, 0x20 },
+       { 0x3445, 0x25 },
+-      { 0x3407, 0x03 },
+       { 0x303a, 0x0c },
+       { 0x3040, 0x00 },
+       { 0x3041, 0x00 },
+@@ -169,7 +173,6 @@ static const struct imx290_regval imx290
+       { 0x3164, 0x1a },
+       { 0x3480, 0x49 },
+       /* data rate settings */
+-      { 0x3009, 0x01 },
+       { 0x3405, 0x10 },
+       { 0x3446, 0x57 },
+       { 0x3447, 0x00 },
+@@ -187,8 +190,6 @@ static const struct imx290_regval imx290
+       { 0x3453, 0x00 },
+       { 0x3454, 0x17 },
+       { 0x3455, 0x00 },
+-      { 0x301c, 0x98 },
+-      { 0x301d, 0x08 },
+ };
+ static const struct imx290_regval imx290_720p_settings[] = {
+@@ -210,7 +211,6 @@ static const struct imx290_regval imx290
+       { 0x3164, 0x1a },
+       { 0x3480, 0x49 },
+       /* data rate settings */
+-      { 0x3009, 0x01 },
+       { 0x3405, 0x10 },
+       { 0x3446, 0x4f },
+       { 0x3447, 0x00 },
+@@ -228,8 +228,6 @@ static const struct imx290_regval imx290
+       { 0x3453, 0x00 },
+       { 0x3454, 0x17 },
+       { 0x3455, 0x00 },
+-      { 0x301c, 0xe4 },
+-      { 0x301d, 0x0c },
+ };
+ static const struct imx290_regval imx290_10bit_settings[] = {
+@@ -250,10 +248,11 @@ static const s64 imx290_link_freq[] = {
+ };
+ /* Mode configs */
+-static const struct imx290_mode imx290_modes[] = {
++static const struct imx290_mode imx290_modes_2lanes[] = {
+       {
+               .width = 1920,
+               .height = 1080,
++              .hmax = 0x1130,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+               .pixel_rate = 178200000,
+@@ -262,6 +261,7 @@ static const struct imx290_mode imx290_m
+       {
+               .width = 1280,
+               .height = 720,
++              .hmax = 0x19c8,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+               .pixel_rate = 178200000,
+@@ -269,6 +269,44 @@ static const struct imx290_mode imx290_m
+       },
+ };
++static const struct imx290_mode imx290_modes_4lanes[] = {
++      {
++              .width = 1920,
++              .height = 1080,
++              .hmax = 0x0898,
++              .data = imx290_1080p_settings,
++              .data_size = ARRAY_SIZE(imx290_1080p_settings),
++              .pixel_rate = 178200000,
++              .link_freq_index = 0,
++      },
++      {
++              .width = 1280,
++              .height = 720,
++              .hmax = 0x0ce4,
++              .data = imx290_720p_settings,
++              .data_size = ARRAY_SIZE(imx290_720p_settings),
++              .pixel_rate = 178200000,
++              .link_freq_index = 0,
++      },
++};
++
++static inline const struct imx290_mode *imx290_modes_ptr(const struct imx290 *imx290)
++{
++      /* We rely on imx290_probe() to ensure that nlanes is either 2 or 4 */
++      if (imx290->nlanes == 2)
++              return imx290_modes_2lanes;
++      else
++              return imx290_modes_4lanes;
++}
++
++static inline int imx290_modes_num(const struct imx290 *imx290)
++{
++      if (imx290->nlanes == 2)
++              return ARRAY_SIZE(imx290_modes_2lanes);
++      else
++              return ARRAY_SIZE(imx290_modes_4lanes);
++}
++
+ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
+ {
+       return container_of(_sd, struct imx290, sd);
+@@ -450,9 +488,8 @@ static int imx290_set_fmt(struct v4l2_su
+       mutex_lock(&imx290->lock);
+-      mode = v4l2_find_nearest_size(imx290_modes,
+-                                    ARRAY_SIZE(imx290_modes),
+-                                    width, height,
++      mode = v4l2_find_nearest_size(imx290_modes_ptr(imx290),
++                                    imx290_modes_num(imx290), width, height,
+                                     fmt->format.width, fmt->format.height);
+       fmt->format.width = mode->width;
+@@ -522,6 +559,25 @@ static int imx290_write_current_format(s
+       return 0;
+ }
++static int imx290_set_hmax(struct imx290 *imx290, u32 val)
++{
++      int ret;
++
++      ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (val & 0xff));
++      if (ret) {
++              dev_err(imx290->dev, "Error setting HMAX register\n");
++              return ret;
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((val >> 8) & 0xff));
++      if (ret) {
++              dev_err(imx290->dev, "Error setting HMAX register\n");
++              return ret;
++      }
++
++      return 0;
++}
++
+ /* Start streaming */
+ static int imx290_start_streaming(struct imx290 *imx290)
+ {
+@@ -550,6 +606,9 @@ static int imx290_start_streaming(struct
+               dev_err(imx290->dev, "Could not set current mode\n");
+               return ret;
+       }
++      ret = imx290_set_hmax(imx290, imx290->current_mode->hmax);
++      if (ret < 0)
++              return ret;
+       /* Apply customized values from user */
+       ret = v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
+@@ -607,6 +666,49 @@ static int imx290_get_regulators(struct
+                                      imx290->supplies);
+ }
++static int imx290_set_data_lanes(struct imx290 *imx290)
++{
++      int ret = 0, laneval, frsel;
++
++      switch (imx290->nlanes) {
++      case 2:
++              laneval = 0x01;
++              frsel = 0x02;
++              break;
++      case 4:
++              laneval = 0x03;
++              frsel = 0x01;
++              break;
++      default:
++              /*
++               * We should never hit this since the data lane count is
++               * validated in probe itself
++               */
++              dev_err(imx290->dev, "Lane configuration not supported\n");
++              ret = -EINVAL;
++              goto exit;
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_PHY_LANE_NUM, laneval);
++      if (ret) {
++              dev_err(imx290->dev, "Error setting Physical Lane number register\n");
++              goto exit;
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_CSI_LANE_MODE, laneval);
++      if (ret) {
++              dev_err(imx290->dev, "Error setting CSI Lane mode register\n");
++              goto exit;
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_FR_FDG_SEL, frsel);
++      if (ret)
++              dev_err(imx290->dev, "Error setting FR/FDG SEL register\n");
++
++exit:
++      return ret;
++}
++
+ static int imx290_power_on(struct device *dev)
+ {
+       struct i2c_client *client = to_i2c_client(dev);
+@@ -631,6 +733,9 @@ static int imx290_power_on(struct device
+       gpiod_set_value_cansleep(imx290->rst_gpio, 0);
+       usleep_range(30000, 31000);
++      /* Set data lane count */
++      imx290_set_data_lanes(imx290);
++
+       return 0;
+ }
+@@ -677,6 +782,7 @@ static int imx290_probe(struct i2c_clien
+       struct fwnode_handle *endpoint;
+       struct imx290 *imx290;
+       u32 xclk_freq;
++      u32 default_pixel_rate;
+       int ret;
+       imx290 = devm_kzalloc(dev, sizeof(*imx290), GFP_KERNEL);
+@@ -703,6 +809,16 @@ static int imx290_probe(struct i2c_clien
+               goto free_err;
+       }
++      /* Get number of data lanes */
++      imx290->nlanes = imx290->ep.bus.mipi_csi2.num_data_lanes;
++      if (imx290->nlanes != 2 && imx290->nlanes != 4) {
++              dev_err(dev, "Invalid data lanes: %d\n", imx290->nlanes);
++              ret = -EINVAL;
++              goto free_err;
++      }
++
++      dev_dbg(dev, "Using %u data lanes\n", imx290->nlanes);
++
+       if (!imx290->ep.nr_of_link_frequencies) {
+               dev_err(dev, "link-frequency property not found in DT\n");
+               ret = -EINVAL;
+@@ -780,10 +896,13 @@ static int imx290_probe(struct i2c_clien
+       if (imx290->link_freq)
+               imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++      default_pixel_rate = imx290->nlanes == 2 ?
++                           imx290_modes_2lanes[0].pixel_rate :
++                           imx290_modes_4lanes[0].pixel_rate;
+       imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                                              V4L2_CID_PIXEL_RATE, 1,
+                                              INT_MAX, 1,
+-                                             imx290_modes[0].pixel_rate);
++                                             default_pixel_rate);
+       imx290->sd.ctrl_handler = &imx290->ctrls;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0821-media-i2c-imx290-Add-configurable-link-frequency-and.patch b/target/linux/bcm27xx/patches-5.4/950-0821-media-i2c-imx290-Add-configurable-link-frequency-and.patch
new file mode 100644 (file)
index 0000000..f746279
--- /dev/null
@@ -0,0 +1,307 @@
+From e3c6ec43e950d9e08715e2c693771080c7d078a3 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:50 +0200
+Subject: [PATCH] media: i2c: imx290: Add configurable link frequency
+ and pixel rate
+
+Commit 98e0500eadb772e1be32d8e369fcc3b7bcac93ed upstream.
+
+IMX290 operates with multiple link frequency and pixel rate combinations.
+The initial driver used a single setting for both but since we now have
+the lane count support in place, let's add configurable link frequency
+and pixel rate.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 148 +++++++++++++++++++++++++++----------
+ 1 file changed, 109 insertions(+), 39 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -32,8 +32,6 @@
+ #define IMX290_PHY_LANE_NUM 0x3407
+ #define IMX290_CSI_LANE_MODE 0x3443
+-#define IMX290_DEFAULT_LINK_FREQ 445500000
+-
+ static const char * const imx290_supply_name[] = {
+       "vdda",
+       "vddd",
+@@ -51,8 +49,7 @@ struct imx290_mode {
+       u32 width;
+       u32 height;
+       u32 hmax;
+-      u32 pixel_rate;
+-      u32 link_freq_index;
++      u8 link_freq_index;
+       const struct imx290_regval *data;
+       u32 data_size;
+@@ -243,9 +240,36 @@ static const struct imx290_regval imx290
+ };
+ /* supported link frequencies */
+-static const s64 imx290_link_freq[] = {
+-      IMX290_DEFAULT_LINK_FREQ,
+-};
++#define FREQ_INDEX_1080P      0
++#define FREQ_INDEX_720P               1
++static const s64 imx290_link_freq_2lanes[] = {
++      [FREQ_INDEX_1080P] = 445500000,
++      [FREQ_INDEX_720P] = 297000000,
++};
++static const s64 imx290_link_freq_4lanes[] = {
++      [FREQ_INDEX_1080P] = 222750000,
++      [FREQ_INDEX_720P] = 148500000,
++};
++
++/*
++ * In this function and in the similar ones below We rely on imx290_probe()
++ * to ensure that nlanes is either 2 or 4.
++ */
++static inline const s64 *imx290_link_freqs_ptr(const struct imx290 *imx290)
++{
++      if (imx290->nlanes == 2)
++              return imx290_link_freq_2lanes;
++      else
++              return imx290_link_freq_4lanes;
++}
++
++static inline int imx290_link_freqs_num(const struct imx290 *imx290)
++{
++      if (imx290->nlanes == 2)
++              return ARRAY_SIZE(imx290_link_freq_2lanes);
++      else
++              return ARRAY_SIZE(imx290_link_freq_4lanes);
++}
+ /* Mode configs */
+ static const struct imx290_mode imx290_modes_2lanes[] = {
+@@ -253,19 +277,17 @@ static const struct imx290_mode imx290_m
+               .width = 1920,
+               .height = 1080,
+               .hmax = 0x1130,
++              .link_freq_index = FREQ_INDEX_1080P,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+-              .pixel_rate = 178200000,
+-              .link_freq_index = 0,
+       },
+       {
+               .width = 1280,
+               .height = 720,
+               .hmax = 0x19c8,
++              .link_freq_index = FREQ_INDEX_720P,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+-              .pixel_rate = 178200000,
+-              .link_freq_index = 0,
+       },
+ };
+@@ -274,25 +296,22 @@ static const struct imx290_mode imx290_m
+               .width = 1920,
+               .height = 1080,
+               .hmax = 0x0898,
++              .link_freq_index = FREQ_INDEX_1080P,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+-              .pixel_rate = 178200000,
+-              .link_freq_index = 0,
+       },
+       {
+               .width = 1280,
+               .height = 720,
+               .hmax = 0x0ce4,
++              .link_freq_index = FREQ_INDEX_720P,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+-              .pixel_rate = 178200000,
+-              .link_freq_index = 0,
+       },
+ };
+ static inline const struct imx290_mode *imx290_modes_ptr(const struct imx290 *imx290)
+ {
+-      /* We rely on imx290_probe() to ensure that nlanes is either 2 or 4 */
+       if (imx290->nlanes == 2)
+               return imx290_modes_2lanes;
+       else
+@@ -477,6 +496,30 @@ static int imx290_get_fmt(struct v4l2_su
+       return 0;
+ }
++static inline u8 imx290_get_link_freq_index(struct imx290 *imx290)
++{
++      return imx290->current_mode->link_freq_index;
++}
++
++static s64 imx290_get_link_freq(struct imx290 *imx290)
++{
++      u8 index = imx290_get_link_freq_index(imx290);
++
++      return *(imx290_link_freqs_ptr(imx290) + index);
++}
++
++static u64 imx290_calc_pixel_rate(struct imx290 *imx290)
++{
++      s64 link_freq = imx290_get_link_freq(imx290);
++      u8 nlanes = imx290->nlanes;
++      u64 pixel_rate;
++
++      /* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
++      pixel_rate = link_freq * 2 * nlanes;
++      do_div(pixel_rate, 10);
++      return pixel_rate;
++}
++
+ static int imx290_set_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                     struct v4l2_subdev_format *fmt)
+@@ -509,10 +552,14 @@ static int imx290_set_fmt(struct v4l2_su
+               format = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+       } else {
+               format = &imx290->current_format;
+-              __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
+-              __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, mode->pixel_rate);
+-
+               imx290->current_mode = mode;
++
++              if (imx290->link_freq)
++                      __v4l2_ctrl_s_ctrl(imx290->link_freq,
++                                         imx290_get_link_freq_index(imx290));
++              if (imx290->pixel_rate)
++                      __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
++                                               imx290_calc_pixel_rate(imx290));
+       }
+       *format = fmt->format;
+@@ -536,12 +583,11 @@ static int imx290_entity_init_cfg(struct
+       return 0;
+ }
+-static int imx290_write_current_format(struct imx290 *imx290,
+-                                     struct v4l2_mbus_framefmt *format)
++static int imx290_write_current_format(struct imx290 *imx290)
+ {
+       int ret;
+-      switch (format->code) {
++      switch (imx290->current_format.code) {
+       case MEDIA_BUS_FMT_SRGGB10_1X10:
+               ret = imx290_set_register_array(imx290, imx290_10bit_settings,
+                                               ARRAY_SIZE(
+@@ -592,8 +638,8 @@ static int imx290_start_streaming(struct
+               return ret;
+       }
+-      /* Set current frame format */
+-      ret = imx290_write_current_format(imx290, &imx290->current_format);
++      /* Apply the register values related to current frame format */
++      ret = imx290_write_current_format(imx290);
+       if (ret < 0) {
+               dev_err(imx290->dev, "Could not set frame format\n");
+               return ret;
+@@ -776,13 +822,34 @@ static const struct media_entity_operati
+       .link_validate = v4l2_subdev_link_validate,
+ };
++/*
++ * Returns 0 if all link frequencies used by the driver for the given number
++ * of MIPI data lanes are mentioned in the device tree, or the value of the
++ * first missing frequency otherwise.
++ */
++static s64 imx290_check_link_freqs(const struct imx290 *imx290)
++{
++      int i, j;
++      const s64 *freqs = imx290_link_freqs_ptr(imx290);
++      int freqs_count = imx290_link_freqs_num(imx290);
++
++      for (i = 0; i < freqs_count; i++) {
++              for (j = 0; j < imx290->ep.nr_of_link_frequencies; j++)
++                      if (freqs[i] == imx290->ep.link_frequencies[j])
++                              break;
++              if (j == imx290->ep.nr_of_link_frequencies)
++                      return freqs[i];
++      }
++      return 0;
++}
++
+ static int imx290_probe(struct i2c_client *client)
+ {
+       struct device *dev = &client->dev;
+       struct fwnode_handle *endpoint;
+       struct imx290 *imx290;
+       u32 xclk_freq;
+-      u32 default_pixel_rate;
++      s64 fq;
+       int ret;
+       imx290 = devm_kzalloc(dev, sizeof(*imx290), GFP_KERNEL);
+@@ -825,8 +892,10 @@ static int imx290_probe(struct i2c_clien
+               goto free_err;
+       }
+-      if (imx290->ep.link_frequencies[0] != IMX290_DEFAULT_LINK_FREQ) {
+-              dev_err(dev, "Unsupported link frequency\n");
++      /* Check that link frequences for all the modes are in device tree */
++      fq = imx290_check_link_freqs(imx290);
++      if (fq) {
++              dev_err(dev, "Link frequency of %lld is not supported\n", fq);
+               ret = -EINVAL;
+               goto free_err;
+       }
+@@ -883,26 +952,30 @@ static int imx290_probe(struct i2c_clien
+       mutex_init(&imx290->lock);
++      /*
++       * Initialize the frame format. In particular, imx290->current_mode
++       * and imx290->bpp are set to defaults: imx290_calc_pixel_rate() call
++       * below relies on these fields.
++       */
++      imx290_entity_init_cfg(&imx290->sd, NULL);
++
+       v4l2_ctrl_handler_init(&imx290->ctrls, 3);
+       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                         V4L2_CID_GAIN, 0, 72, 1, 0);
++
+       imx290->link_freq =
+-              v4l2_ctrl_new_int_menu(&imx290->ctrls,
+-                                     &imx290_ctrl_ops,
++              v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+                                      V4L2_CID_LINK_FREQ,
+-                                     ARRAY_SIZE(imx290_link_freq) - 1,
+-                                     0, imx290_link_freq);
++                                     imx290_link_freqs_num(imx290) - 1, 0,
++                                     imx290_link_freqs_ptr(imx290));
+       if (imx290->link_freq)
+               imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-      default_pixel_rate = imx290->nlanes == 2 ?
+-                           imx290_modes_2lanes[0].pixel_rate :
+-                           imx290_modes_4lanes[0].pixel_rate;
+       imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+-                                             V4L2_CID_PIXEL_RATE, 1,
+-                                             INT_MAX, 1,
+-                                             default_pixel_rate);
++                                             V4L2_CID_PIXEL_RATE,
++                                             1, INT_MAX, 1,
++                                             imx290_calc_pixel_rate(imx290));
+       imx290->sd.ctrl_handler = &imx290->ctrls;
+@@ -926,9 +999,6 @@ static int imx290_probe(struct i2c_clien
+               goto free_ctrl;
+       }
+-      /* Initialize the frame format (this also sets imx290->current_mode) */
+-      imx290_entity_init_cfg(&imx290->sd, NULL);
+-
+       ret = v4l2_async_register_subdev(&imx290->sd);
+       if (ret < 0) {
+               dev_err(dev, "Could not register v4l2 device\n");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0822-media-i2c-imx290-Add-support-for-test-pattern-genera.patch b/target/linux/bcm27xx/patches-5.4/950-0822-media-i2c-imx290-Add-support-for-test-pattern-genera.patch
new file mode 100644 (file)
index 0000000..e7900ab
--- /dev/null
@@ -0,0 +1,110 @@
+From f1a8ae8064a65846489386fe95790900fb150242 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:51 +0200
+Subject: [PATCH] media: i2c: imx290: Add support for test pattern
+ generation
+
+Commit a58df1f9e4885eaf3d0663574a217e513821a9f0 upstream.
+
+Add support for generating following test patterns by IMX290:
+
+* Sequence Pattern 1
+* Horizontal Color-bar Chart
+* Vertical Color-bar Chart
+* Sequence Pattern 2
+* Gradation Pattern 1
+* Gradation Pattern 2
+* 000/555h Toggle Pattern
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 41 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 40 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -26,12 +26,19 @@
+ #define IMX290_REGHOLD 0x3001
+ #define IMX290_XMSTA 0x3002
+ #define IMX290_FR_FDG_SEL 0x3009
++#define IMX290_BLKLEVEL_LOW 0x300a
++#define IMX290_BLKLEVEL_HIGH 0x300b
+ #define IMX290_GAIN 0x3014
+ #define IMX290_HMAX_LOW 0x301c
+ #define IMX290_HMAX_HIGH 0x301d
++#define IMX290_PGCTRL 0x308c
+ #define IMX290_PHY_LANE_NUM 0x3407
+ #define IMX290_CSI_LANE_MODE 0x3443
++#define IMX290_PGCTRL_REGEN BIT(0)
++#define IMX290_PGCTRL_THRU BIT(1)
++#define IMX290_PGCTRL_MODE(n) ((n) << 4)
++
+ static const char * const imx290_supply_name[] = {
+       "vdda",
+       "vddd",
+@@ -91,6 +98,17 @@ static const struct regmap_config imx290
+       .cache_type = REGCACHE_RBTREE,
+ };
++static const char * const imx290_test_pattern_menu[] = {
++      "Disabled",
++      "Sequence Pattern 1",
++      "Horizontal Color-bar Chart",
++      "Vertical Color-bar Chart",
++      "Sequence Pattern 2",
++      "Gradation Pattern 1",
++      "Gradation Pattern 2",
++      "000/555h Toggle Pattern",
++};
++
+ static const struct imx290_regval imx290_global_init_settings[] = {
+       { 0x3007, 0x00 },
+       { 0x3018, 0x65 },
+@@ -448,6 +466,22 @@ static int imx290_set_ctrl(struct v4l2_c
+       case V4L2_CID_GAIN:
+               ret = imx290_set_gain(imx290, ctrl->val);
+               break;
++      case V4L2_CID_TEST_PATTERN:
++              if (ctrl->val) {
++                      imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
++                      imx290_write_reg(imx290, IMX290_BLKLEVEL_HIGH, 0x00);
++                      msleep(10);
++                      imx290_write_reg(imx290, IMX290_PGCTRL,
++                                       (u8)(IMX290_PGCTRL_REGEN |
++                                       IMX290_PGCTRL_THRU |
++                                       IMX290_PGCTRL_MODE(ctrl->val)));
++              } else {
++                      imx290_write_reg(imx290, IMX290_PGCTRL, 0x00);
++                      msleep(10);
++                      imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x3c);
++                      imx290_write_reg(imx290, IMX290_BLKLEVEL_HIGH, 0x00);
++              }
++              break;
+       default:
+               ret = -EINVAL;
+               break;
+@@ -959,7 +993,7 @@ static int imx290_probe(struct i2c_clien
+        */
+       imx290_entity_init_cfg(&imx290->sd, NULL);
+-      v4l2_ctrl_handler_init(&imx290->ctrls, 3);
++      v4l2_ctrl_handler_init(&imx290->ctrls, 4);
+       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                         V4L2_CID_GAIN, 0, 72, 1, 0);
+@@ -977,6 +1011,11 @@ static int imx290_probe(struct i2c_clien
+                                              1, INT_MAX, 1,
+                                              imx290_calc_pixel_rate(imx290));
++      v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
++                                   V4L2_CID_TEST_PATTERN,
++                                   ARRAY_SIZE(imx290_test_pattern_menu) - 1,
++                                   0, 0, imx290_test_pattern_menu);
++
+       imx290->sd.ctrl_handler = &imx290->ctrls;
+       if (imx290->ctrls.error) {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0823-media-i2c-imx290-Add-RAW12-mode-support.patch b/target/linux/bcm27xx/patches-5.4/950-0823-media-i2c-imx290-Add-RAW12-mode-support.patch
new file mode 100644 (file)
index 0000000..6e43735
--- /dev/null
@@ -0,0 +1,109 @@
+From 9f6a310ab3b466940c0a15260987d4cfe868a79a Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:52 +0200
+Subject: [PATCH] media: i2c: imx290: Add RAW12 mode support
+
+Commit c566ac01ceaa02450acc155201772c0623530e76 upstream.
+
+IMX290 is capable of outputting frames in both Raw Bayer (packed) 10 and
+12 bit formats. Since the driver already supports RAW10 mode, let's add
+the missing RAW12 mode as well.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 36 +++++++++++++++++++++++++++++++++---
+ 1 file changed, 33 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -67,6 +67,7 @@ struct imx290 {
+       struct clk *xclk;
+       struct regmap *regmap;
+       u8 nlanes;
++      u8 bpp;
+       struct v4l2_subdev sd;
+       struct v4l2_fwnode_endpoint ep;
+@@ -86,10 +87,12 @@ struct imx290 {
+ struct imx290_pixfmt {
+       u32 code;
++      u8 bpp;
+ };
+ static const struct imx290_pixfmt imx290_formats[] = {
+-      { MEDIA_BUS_FMT_SRGGB10_1X10 },
++      { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
++      { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
+ };
+ static const struct regmap_config imx290_regmap_config = {
+@@ -257,6 +260,18 @@ static const struct imx290_regval imx290
+       { 0x300b, 0x00},
+ };
++static const struct imx290_regval imx290_12bit_settings[] = {
++      { 0x3005, 0x01 },
++      { 0x3046, 0x01 },
++      { 0x3129, 0x00 },
++      { 0x317c, 0x00 },
++      { 0x31ec, 0x0e },
++      { 0x3441, 0x0c },
++      { 0x3442, 0x0c },
++      { 0x300a, 0xf0 },
++      { 0x300b, 0x00 },
++};
++
+ /* supported link frequencies */
+ #define FREQ_INDEX_1080P      0
+ #define FREQ_INDEX_720P               1
+@@ -478,7 +493,12 @@ static int imx290_set_ctrl(struct v4l2_c
+               } else {
+                       imx290_write_reg(imx290, IMX290_PGCTRL, 0x00);
+                       msleep(10);
+-                      imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x3c);
++                      if (imx290->bpp == 10)
++                              imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW,
++                                               0x3c);
++                      else /* 12 bits per pixel */
++                              imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW,
++                                               0xf0);
+                       imx290_write_reg(imx290, IMX290_BLKLEVEL_HIGH, 0x00);
+               }
+               break;
+@@ -550,7 +570,7 @@ static u64 imx290_calc_pixel_rate(struct
+       /* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
+       pixel_rate = link_freq * 2 * nlanes;
+-      do_div(pixel_rate, 10);
++      do_div(pixel_rate, imx290->bpp);
+       return pixel_rate;
+ }
+@@ -587,6 +607,7 @@ static int imx290_set_fmt(struct v4l2_su
+       } else {
+               format = &imx290->current_format;
+               imx290->current_mode = mode;
++              imx290->bpp = imx290_formats[i].bpp;
+               if (imx290->link_freq)
+                       __v4l2_ctrl_s_ctrl(imx290->link_freq,
+@@ -629,6 +650,15 @@ static int imx290_write_current_format(s
+               if (ret < 0) {
+                       dev_err(imx290->dev, "Could not set format registers\n");
+                       return ret;
++              }
++              break;
++      case MEDIA_BUS_FMT_SRGGB12_1X12:
++              ret = imx290_set_register_array(imx290, imx290_12bit_settings,
++                                              ARRAY_SIZE(
++                                                      imx290_12bit_settings));
++              if (ret < 0) {
++                      dev_err(imx290->dev, "Could not set format registers\n");
++                      return ret;
+               }
+               break;
+       default:
diff --git a/target/linux/bcm27xx/patches-5.4/950-0824-media-i2c-imx290-Add-support-to-enumerate-all-frame-.patch b/target/linux/bcm27xx/patches-5.4/950-0824-media-i2c-imx290-Add-support-to-enumerate-all-frame-.patch
new file mode 100644 (file)
index 0000000..8ae528a
--- /dev/null
@@ -0,0 +1,58 @@
+From 9ca04663315302f1556798e9da29eabf08aecd59 Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:53 +0200
+Subject: [PATCH] media: i2c: imx290: Add support to enumerate all
+ frame sizes
+
+Commit 3b867fb641d884b714fba390ae866714ba475f29 upstream.
+
+Add support to enumerate all frame sizes supported by IMX290. This is
+required for using with userspace tools such as libcamera.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -528,6 +528,28 @@ static int imx290_enum_mbus_code(struct
+       return 0;
+ }
++static int imx290_enum_frame_size(struct v4l2_subdev *sd,
++                                struct v4l2_subdev_pad_config *cfg,
++                                struct v4l2_subdev_frame_size_enum *fse)
++{
++      const struct imx290 *imx290 = to_imx290(sd);
++      const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
++
++      if ((fse->code != imx290_formats[0].code) &&
++          (fse->code != imx290_formats[1].code))
++              return -EINVAL;
++
++      if (fse->index >= imx290_modes_num(imx290))
++              return -EINVAL;
++
++      fse->min_width = imx290_modes[fse->index].width;
++      fse->max_width = imx290_modes[fse->index].width;
++      fse->min_height = imx290_modes[fse->index].height;
++      fse->max_height = imx290_modes[fse->index].height;
++
++      return 0;
++}
++
+ static int imx290_get_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *fmt)
+@@ -873,6 +895,7 @@ static const struct v4l2_subdev_video_op
+ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
+       .init_cfg = imx290_entity_init_cfg,
+       .enum_mbus_code = imx290_enum_mbus_code,
++      .enum_frame_size = imx290_enum_frame_size,
+       .get_fmt = imx290_get_fmt,
+       .set_fmt = imx290_set_fmt,
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0825-media-i2c-imx290-Move-the-settle-time-delay-out-of-l.patch b/target/linux/bcm27xx/patches-5.4/950-0825-media-i2c-imx290-Move-the-settle-time-delay-out-of-l.patch
new file mode 100644 (file)
index 0000000..a46c0c9
--- /dev/null
@@ -0,0 +1,37 @@
+From d2155366275ce70438d12169a59959e90b637f9c Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:54 +0200
+Subject: [PATCH] media: i2c: imx290: Move the settle time delay out
+ of loop
+
+Commit 6544af9b04b4484867c234ba0be1b5008e4a14ee upstream.
+
+The 10ms settle time is needed only at the end of all consecutive
+register writes. So move the delay to outside of the for loop of
+imx290_set_register_array().
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -404,11 +404,11 @@ static int imx290_set_register_array(str
+               ret = imx290_write_reg(imx290, settings->reg, settings->val);
+               if (ret < 0)
+                       return ret;
+-
+-              /* Settle time is 10ms for all registers */
+-              msleep(10);
+       }
++      /* Provide 10ms settle time */
++      msleep(10);
++
+       return 0;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0826-media-i2c-imx290-set-bus_type-before-calling-v4l2_fw.patch b/target/linux/bcm27xx/patches-5.4/950-0826-media-i2c-imx290-set-bus_type-before-calling-v4l2_fw.patch
new file mode 100644 (file)
index 0000000..5180ee6
--- /dev/null
@@ -0,0 +1,137 @@
+From e5b34fd95be9c59fe55e4755ba84aa05efaaaf62 Mon Sep 17 00:00:00 2001
+From: Andrey Konovalov <andrey.konovalov@linaro.org>
+Date: Fri, 12 Jun 2020 15:53:55 +0200
+Subject: [PATCH] media: i2c: imx290: set bus_type before calling
+ v4l2_fwnode_endpoint_alloc_parse()
+
+Commit a270675875829b6d46eb9e38960fd6019555ebb8 upstream.
+
+The bus_type field of v4l2_fwnode_endpoint structure passed as the argument
+to v4l2_fwnode_endpoint_alloc_parse() function must be initiaized.
+Set it to V4L2_MBUS_CSI2_DPHY, and check for -ENXIO which is returned
+when the requested media bus type doesn't match the fwnode.
+
+Also remove v4l2_fwnode_endpoint field from struct imx290 as it is only
+needed in the probe function: use the local variable for this purpose.
+
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ drivers/media/i2c/imx290.c | 38 +++++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -70,7 +70,6 @@ struct imx290 {
+       u8 bpp;
+       struct v4l2_subdev sd;
+-      struct v4l2_fwnode_endpoint ep;
+       struct media_pad pad;
+       struct v4l2_mbus_framefmt current_format;
+       const struct imx290_mode *current_mode;
+@@ -914,17 +913,18 @@ static const struct media_entity_operati
+  * of MIPI data lanes are mentioned in the device tree, or the value of the
+  * first missing frequency otherwise.
+  */
+-static s64 imx290_check_link_freqs(const struct imx290 *imx290)
++static s64 imx290_check_link_freqs(const struct imx290 *imx290,
++                                 const struct v4l2_fwnode_endpoint *ep)
+ {
+       int i, j;
+       const s64 *freqs = imx290_link_freqs_ptr(imx290);
+       int freqs_count = imx290_link_freqs_num(imx290);
+       for (i = 0; i < freqs_count; i++) {
+-              for (j = 0; j < imx290->ep.nr_of_link_frequencies; j++)
+-                      if (freqs[i] == imx290->ep.link_frequencies[j])
++              for (j = 0; j < ep->nr_of_link_frequencies; j++)
++                      if (freqs[i] == ep->link_frequencies[j])
+                               break;
+-              if (j == imx290->ep.nr_of_link_frequencies)
++              if (j == ep->nr_of_link_frequencies)
+                       return freqs[i];
+       }
+       return 0;
+@@ -934,6 +934,10 @@ static int imx290_probe(struct i2c_clien
+ {
+       struct device *dev = &client->dev;
+       struct fwnode_handle *endpoint;
++      /* Only CSI2 is supported for now: */
++      struct v4l2_fwnode_endpoint ep = {
++              .bus_type = V4L2_MBUS_CSI2_DPHY
++      };
+       struct imx290 *imx290;
+       u32 xclk_freq;
+       s64 fq;
+@@ -956,15 +960,18 @@ static int imx290_probe(struct i2c_clien
+               return -EINVAL;
+       }
+-      ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &imx290->ep);
++      ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep);
+       fwnode_handle_put(endpoint);
+-      if (ret) {
++      if (ret == -ENXIO) {
++              dev_err(dev, "Unsupported bus type, should be CSI2\n");
++              goto free_err;
++      } else if (ret) {
+               dev_err(dev, "Parsing endpoint node failed\n");
+               goto free_err;
+       }
+       /* Get number of data lanes */
+-      imx290->nlanes = imx290->ep.bus.mipi_csi2.num_data_lanes;
++      imx290->nlanes = ep.bus.mipi_csi2.num_data_lanes;
+       if (imx290->nlanes != 2 && imx290->nlanes != 4) {
+               dev_err(dev, "Invalid data lanes: %d\n", imx290->nlanes);
+               ret = -EINVAL;
+@@ -973,27 +980,20 @@ static int imx290_probe(struct i2c_clien
+       dev_dbg(dev, "Using %u data lanes\n", imx290->nlanes);
+-      if (!imx290->ep.nr_of_link_frequencies) {
++      if (!ep.nr_of_link_frequencies) {
+               dev_err(dev, "link-frequency property not found in DT\n");
+               ret = -EINVAL;
+               goto free_err;
+       }
+       /* Check that link frequences for all the modes are in device tree */
+-      fq = imx290_check_link_freqs(imx290);
++      fq = imx290_check_link_freqs(imx290, &ep);
+       if (fq) {
+               dev_err(dev, "Link frequency of %lld is not supported\n", fq);
+               ret = -EINVAL;
+               goto free_err;
+       }
+-      /* Only CSI2 is supported for now */
+-      if (imx290->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
+-              dev_err(dev, "Unsupported bus type, should be CSI2\n");
+-              ret = -EINVAL;
+-              goto free_err;
+-      }
+-
+       /* get system clock (xclk) */
+       imx290->xclk = devm_clk_get(dev, "xclk");
+       if (IS_ERR(imx290->xclk)) {
+@@ -1108,7 +1108,7 @@ static int imx290_probe(struct i2c_clien
+       pm_runtime_enable(dev);
+       pm_runtime_idle(dev);
+-      v4l2_fwnode_endpoint_free(&imx290->ep);
++      v4l2_fwnode_endpoint_free(&ep);
+       return 0;
+@@ -1118,7 +1118,7 @@ free_ctrl:
+       v4l2_ctrl_handler_free(&imx290->ctrls);
+       mutex_destroy(&imx290->lock);
+ free_err:
+-      v4l2_fwnode_endpoint_free(&imx290->ep);
++      v4l2_fwnode_endpoint_free(&ep);
+       return ret;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch b/target/linux/bcm27xx/patches-5.4/950-0827-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch
new file mode 100644 (file)
index 0000000..87661b7
--- /dev/null
@@ -0,0 +1,264 @@
+From c175c735869b0dfa8c21fc57d5bd02ca370f9117 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 08:28:51 +0100
+Subject: [PATCH] media: i2c: imx290: Add support for 74.25MHz clock
+
+The existing driver only supported a clock of 37.125MHz, but the
+sensor also supports 74.25MHz.
+
+Add the relevant register modifications to support this alternate
+clock frequency.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 119 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 97 insertions(+), 22 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -1,6 +1,10 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * Sony IMX290 CMOS Image Sensor Driver
++ * Sony IMX290/327 CMOS Image Sensor Driver
++ *
++ * The IMX290 and IMX327 are very similar 1920x1080 1/2.8 CMOS image sensors.
++ * IMX327 can support up to 60fps, whilst IMX290 support up to 120fps (only
++ * 10bit and when connected over 4 CSI-2 lanes).
+  *
+  * Copyright (C) 2019 FRAMOS GmbH.
+  *
+@@ -22,6 +26,11 @@
+ #include <media/v4l2-fwnode.h>
+ #include <media/v4l2-subdev.h>
++enum imx290_clk_index {
++      CLK_37_125,
++      CLK_74_25,
++};
++
+ #define IMX290_STANDBY 0x3000
+ #define IMX290_REGHOLD 0x3001
+ #define IMX290_XMSTA 0x3002
+@@ -60,11 +69,16 @@ struct imx290_mode {
+       const struct imx290_regval *data;
+       u32 data_size;
++
++      /* Clock setup can vary. Index as enum imx290_clk_index */
++      const struct imx290_regval *clk_data[2];
++      u32 clk_size;
+ };
+ struct imx290 {
+       struct device *dev;
+       struct clk *xclk;
++      u32 xclk_freq;
+       struct regmap *regmap;
+       u8 nlanes;
+       u8 bpp;
+@@ -116,8 +130,6 @@ static const struct imx290_regval imx290
+       { 0x3018, 0x65 },
+       { 0x3019, 0x04 },
+       { 0x301a, 0x00 },
+-      { 0x3444, 0x20 },
+-      { 0x3445, 0x25 },
+       { 0x303a, 0x0c },
+       { 0x3040, 0x00 },
+       { 0x3041, 0x00 },
+@@ -171,6 +183,30 @@ static const struct imx290_regval imx290
+       { 0x33b3, 0x04 },
+ };
++static const struct imx290_regval imx290_37_125mhz_clock_1080p[] = {
++      { 0x305c, 0x18 },
++      { 0x305d, 0x03 },
++      { 0x305e, 0x20 },
++      { 0x305f, 0x01 },
++      { 0x315e, 0x1a },
++      { 0x3164, 0x1a },
++      { 0x3444, 0x20 },
++      { 0x3445, 0x25 },
++      { 0x3480, 0x49 },
++};
++
++static const struct imx290_regval imx290_74_250mhz_clock_1080p[] = {
++      { 0x305c, 0x0c },
++      { 0x305d, 0x03 },
++      { 0x305e, 0x10 },
++      { 0x305f, 0x01 },
++      { 0x315e, 0x1b },
++      { 0x3164, 0x1b },
++      { 0x3444, 0x40 },
++      { 0x3445, 0x4a },
++      { 0x3480, 0x92 },
++};
++
+ static const struct imx290_regval imx290_1080p_settings[] = {
+       /* mode settings */
+       { 0x3007, 0x00 },
+@@ -182,13 +218,6 @@ static const struct imx290_regval imx290
+       { 0x3419, 0x04 },
+       { 0x3012, 0x64 },
+       { 0x3013, 0x00 },
+-      { 0x305c, 0x18 },
+-      { 0x305d, 0x03 },
+-      { 0x305e, 0x20 },
+-      { 0x305f, 0x01 },
+-      { 0x315e, 0x1a },
+-      { 0x3164, 0x1a },
+-      { 0x3480, 0x49 },
+       /* data rate settings */
+       { 0x3405, 0x10 },
+       { 0x3446, 0x57 },
+@@ -209,6 +238,30 @@ static const struct imx290_regval imx290
+       { 0x3455, 0x00 },
+ };
++static const struct imx290_regval imx290_37_125mhz_clock_720p[] = {
++      { 0x305c, 0x20 },
++      { 0x305d, 0x00 },
++      { 0x305e, 0x20 },
++      { 0x305f, 0x01 },
++      { 0x315e, 0x1a },
++      { 0x3164, 0x1a },
++      { 0x3444, 0x20 },
++      { 0x3445, 0x25 },
++      { 0x3480, 0x49 },
++};
++
++static const struct imx290_regval imx290_74_250mhz_clock_720p[] = {
++      { 0x305c, 0x10 },
++      { 0x305d, 0x00 },
++      { 0x305e, 0x10 },
++      { 0x305f, 0x01 },
++      { 0x315e, 0x1b },
++      { 0x3164, 0x1b },
++      { 0x3444, 0x40 },
++      { 0x3445, 0x4a },
++      { 0x3480, 0x92 },
++};
++
+ static const struct imx290_regval imx290_720p_settings[] = {
+       /* mode settings */
+       { 0x3007, 0x10 },
+@@ -220,13 +273,6 @@ static const struct imx290_regval imx290
+       { 0x3419, 0x02 },
+       { 0x3012, 0x64 },
+       { 0x3013, 0x00 },
+-      { 0x305c, 0x20 },
+-      { 0x305d, 0x00 },
+-      { 0x305e, 0x20 },
+-      { 0x305f, 0x01 },
+-      { 0x315e, 0x1a },
+-      { 0x3164, 0x1a },
+-      { 0x3480, 0x49 },
+       /* data rate settings */
+       { 0x3405, 0x10 },
+       { 0x3446, 0x4f },
+@@ -312,6 +358,11 @@ static const struct imx290_mode imx290_m
+               .link_freq_index = FREQ_INDEX_1080P,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
++              .clk_data = {
++                      [CLK_37_125] = imx290_37_125mhz_clock_1080p,
++                      [CLK_74_25] = imx290_74_250mhz_clock_1080p,
++              },
++              .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_1080p),
+       },
+       {
+               .width = 1280,
+@@ -320,6 +371,11 @@ static const struct imx290_mode imx290_m
+               .link_freq_index = FREQ_INDEX_720P,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
++              .clk_data = {
++                      [CLK_37_125] = imx290_37_125mhz_clock_1080p,
++                      [CLK_74_25] = imx290_74_250mhz_clock_1080p,
++              },
++              .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_1080p),
+       },
+ };
+@@ -331,6 +387,11 @@ static const struct imx290_mode imx290_m
+               .link_freq_index = FREQ_INDEX_1080P,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
++              .clk_data = {
++                      [CLK_37_125] = imx290_37_125mhz_clock_720p,
++                      [CLK_74_25] = imx290_74_250mhz_clock_720p,
++              },
++              .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_720p),
+       },
+       {
+               .width = 1280,
+@@ -339,6 +400,11 @@ static const struct imx290_mode imx290_m
+               .link_freq_index = FREQ_INDEX_720P,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
++              .clk_data = {
++                      [CLK_37_125] = imx290_37_125mhz_clock_720p,
++                      [CLK_74_25] = imx290_74_250mhz_clock_720p,
++              },
++              .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_720p),
+       },
+ };
+@@ -712,6 +778,8 @@ static int imx290_set_hmax(struct imx290
+ /* Start streaming */
+ static int imx290_start_streaming(struct imx290 *imx290)
+ {
++      enum imx290_clk_index clk_idx = imx290->xclk_freq == 37125000 ?
++                                      CLK_37_125 : CLK_74_25;
+       int ret;
+       /* Set init register settings */
+@@ -723,6 +791,14 @@ static int imx290_start_streaming(struct
+               return ret;
+       }
++      ret = imx290_set_register_array(imx290,
++                                      imx290->current_mode->clk_data[clk_idx],
++                                      imx290->current_mode->clk_size);
++      if (ret < 0) {
++              dev_err(imx290->dev, "Could not set clock registers\n");
++              return ret;
++      }
++
+       /* Apply the register values related to current frame format */
+       ret = imx290_write_current_format(imx290);
+       if (ret < 0) {
+@@ -939,7 +1015,6 @@ static int imx290_probe(struct i2c_clien
+               .bus_type = V4L2_MBUS_CSI2_DPHY
+       };
+       struct imx290 *imx290;
+-      u32 xclk_freq;
+       s64 fq;
+       int ret;
+@@ -1003,21 +1078,21 @@ static int imx290_probe(struct i2c_clien
+       }
+       ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
+-                                     &xclk_freq);
++                                     &imx290->xclk_freq);
+       if (ret) {
+               dev_err(dev, "Could not get xclk frequency\n");
+               goto free_err;
+       }
+       /* external clock must be 37.125 MHz */
+-      if (xclk_freq != 37125000) {
++      if (imx290->xclk_freq != 37125000 && imx290->xclk_freq != 74250000) {
+               dev_err(dev, "External clock frequency %u is not supported\n",
+-                      xclk_freq);
++                      imx290->xclk_freq);
+               ret = -EINVAL;
+               goto free_err;
+       }
+-      ret = clk_set_rate(imx290->xclk, xclk_freq);
++      ret = clk_set_rate(imx290->xclk, imx290->xclk_freq);
+       if (ret) {
+               dev_err(dev, "Could not set xclk frequency\n");
+               goto free_err;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0828-media-i2c-imx290-Correct-range-for-V4L2_CID_GAIN-to-.patch b/target/linux/bcm27xx/patches-5.4/950-0828-media-i2c-imx290-Correct-range-for-V4L2_CID_GAIN-to-.patch
new file mode 100644 (file)
index 0000000..462c88d
--- /dev/null
@@ -0,0 +1,26 @@
+From 6d659cddefb5f9f35160f4b7b8d5a77935480b2d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 11 Jun 2020 13:41:43 +0100
+Subject: [PATCH] media: i2c: imx290: Correct range for V4L2_CID_GAIN
+ to 0-238
+
+The datasheet lists the gain as being 0.0 to 72.0dB in 0.3dB steps, which
+makes 238 steps total.
+Correct the 0-72 range defined in the driver.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -1124,7 +1124,7 @@ static int imx290_probe(struct i2c_clien
+       v4l2_ctrl_handler_init(&imx290->ctrls, 4);
+       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+-                        V4L2_CID_GAIN, 0, 72, 1, 0);
++                        V4L2_CID_GAIN, 0, 238, 1, 0);
+       imx290->link_freq =
+               v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch b/target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch
new file mode 100644 (file)
index 0000000..7a0a5f0
--- /dev/null
@@ -0,0 +1,159 @@
+From 116dc059ca9c6b088afba98dde7b679a97ae7198 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 11 Jun 2020 14:36:40 +0100
+Subject: [PATCH] media: i2c: imx290: Convert HMAX setting into
+ V4L2_CID_HBLANK
+
+Userspace needs to know HBLANK if it is to work out exposure times
+and frame rates, therefore convert it to map onto V4L2_CID_HBLANK
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 66 +++++++++++++++++++++++++-------------
+ 1 file changed, 44 insertions(+), 22 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -40,6 +40,9 @@ enum imx290_clk_index {
+ #define IMX290_GAIN 0x3014
+ #define IMX290_HMAX_LOW 0x301c
+ #define IMX290_HMAX_HIGH 0x301d
++#define IMX290_HMAX_MIN_2LANE 4400 /* Min of 4400 pixels = 30fps */
++#define IMX290_HMAX_MIN_4LANE 2200 /* Min of 2200 pixels = 60fps */
++#define IMX290_HMAX_MAX 0xffff
+ #define IMX290_PGCTRL 0x308c
+ #define IMX290_PHY_LANE_NUM 0x3407
+ #define IMX290_CSI_LANE_MODE 0x3443
+@@ -82,6 +85,7 @@ struct imx290 {
+       struct regmap *regmap;
+       u8 nlanes;
+       u8 bpp;
++      u16 hmax_min;
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+@@ -94,6 +98,7 @@ struct imx290 {
+       struct v4l2_ctrl_handler ctrls;
+       struct v4l2_ctrl *link_freq;
+       struct v4l2_ctrl *pixel_rate;
++      struct v4l2_ctrl *hblank;
+       struct mutex lock;
+ };
+@@ -518,6 +523,26 @@ static int imx290_set_gain(struct imx290
+       return ret;
+ }
++static int imx290_set_hmax(struct imx290 *imx290, u32 val)
++{
++      u32 hmax = val + imx290->current_mode->width;
++      int ret;
++
++      ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (hmax & 0xff));
++      if (ret) {
++              dev_err(imx290->dev, "Error setting HMAX register\n");
++              return ret;
++      }
++
++      ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((hmax >> 8) & 0xff));
++      if (ret) {
++              dev_err(imx290->dev, "Error setting HMAX register\n");
++              return ret;
++      }
++
++      return 0;
++}
++
+ /* Stop streaming */
+ static int imx290_stop_streaming(struct imx290 *imx290)
+ {
+@@ -546,6 +571,9 @@ static int imx290_set_ctrl(struct v4l2_c
+       case V4L2_CID_GAIN:
+               ret = imx290_set_gain(imx290, ctrl->val);
+               break;
++      case V4L2_CID_HBLANK:
++              ret = imx290_set_hmax(imx290, ctrl->val);
++              break;
+       case V4L2_CID_TEST_PATTERN:
+               if (ctrl->val) {
+                       imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
+@@ -702,6 +730,12 @@ static int imx290_set_fmt(struct v4l2_su
+               if (imx290->pixel_rate)
+                       __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
+                                                imx290_calc_pixel_rate(imx290));
++
++              if (imx290->hblank)
++                      __v4l2_ctrl_modify_range(imx290->hblank,
++                                               imx290->hmax_min - mode->width,
++                                               IMX290_HMAX_MAX - mode->width,
++                                               1, mode->hmax - mode->width);
+       }
+       *format = fmt->format;
+@@ -756,25 +790,6 @@ static int imx290_write_current_format(s
+       return 0;
+ }
+-static int imx290_set_hmax(struct imx290 *imx290, u32 val)
+-{
+-      int ret;
+-
+-      ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (val & 0xff));
+-      if (ret) {
+-              dev_err(imx290->dev, "Error setting HMAX register\n");
+-              return ret;
+-      }
+-
+-      ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((val >> 8) & 0xff));
+-      if (ret) {
+-              dev_err(imx290->dev, "Error setting HMAX register\n");
+-              return ret;
+-      }
+-
+-      return 0;
+-}
+-
+ /* Start streaming */
+ static int imx290_start_streaming(struct imx290 *imx290)
+ {
+@@ -813,9 +828,6 @@ static int imx290_start_streaming(struct
+               dev_err(imx290->dev, "Could not set current mode\n");
+               return ret;
+       }
+-      ret = imx290_set_hmax(imx290, imx290->current_mode->hmax);
+-      if (ret < 0)
+-              return ret;
+       /* Apply customized values from user */
+       ret = v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
+@@ -1014,6 +1026,7 @@ static int imx290_probe(struct i2c_clien
+       struct v4l2_fwnode_endpoint ep = {
+               .bus_type = V4L2_MBUS_CSI2_DPHY
+       };
++      const struct imx290_mode *mode;
+       struct imx290 *imx290;
+       s64 fq;
+       int ret;
+@@ -1052,6 +1065,8 @@ static int imx290_probe(struct i2c_clien
+               ret = -EINVAL;
+               goto free_err;
+       }
++      imx290->hmax_min = (imx290->nlanes == 2) ? IMX290_HMAX_MIN_2LANE :
++                                               IMX290_HMAX_MIN_4LANE;
+       dev_dbg(dev, "Using %u data lanes\n", imx290->nlanes);
+@@ -1126,6 +1141,13 @@ static int imx290_probe(struct i2c_clien
+       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+                         V4L2_CID_GAIN, 0, 238, 1, 0);
++      mode = imx290->current_mode;
++      imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                                         V4L2_CID_HBLANK,
++                                         imx290->hmax_min - mode->width,
++                                         IMX290_HMAX_MAX - mode->width, 1,
++                                         mode->hmax - mode->width);
++
+       imx290->link_freq =
+               v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+                                      V4L2_CID_LINK_FREQ,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0830-media-i2c-imx290-Add-support-for-V4L2_CID_VBLANK.patch b/target/linux/bcm27xx/patches-5.4/950-0830-media-i2c-imx290-Add-support-for-V4L2_CID_VBLANK.patch
new file mode 100644 (file)
index 0000000..daa5d54
--- /dev/null
@@ -0,0 +1,141 @@
+From 12a04a18c7a56dbd2943b6666c7978b09499fc4b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 11 Jun 2020 18:09:12 +0100
+Subject: [PATCH] media: i2c: imx290: Add support for V4L2_CID_VBLANK
+
+In order to calculate framerate and durations userspace needs
+the vertical blanking information. This can be configurable,
+and indeed the datasheet lists different values for VBLANK for
+the 1080p and 720p modes.
+
+Add the new control, and adopt the datasheet values for each mode.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 38 ++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 36 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -38,6 +38,8 @@ enum imx290_clk_index {
+ #define IMX290_BLKLEVEL_LOW 0x300a
+ #define IMX290_BLKLEVEL_HIGH 0x300b
+ #define IMX290_GAIN 0x3014
++#define IMX290_VMAX_LOW 0x3018
++#define IMX290_VMAX_MAX 0x3fff
+ #define IMX290_HMAX_LOW 0x301c
+ #define IMX290_HMAX_HIGH 0x301d
+ #define IMX290_HMAX_MIN_2LANE 4400 /* Min of 4400 pixels = 30fps */
+@@ -68,6 +70,7 @@ struct imx290_mode {
+       u32 width;
+       u32 height;
+       u32 hmax;
++      u32 vmax;
+       u8 link_freq_index;
+       const struct imx290_regval *data;
+@@ -99,6 +102,7 @@ struct imx290 {
+       struct v4l2_ctrl *link_freq;
+       struct v4l2_ctrl *pixel_rate;
+       struct v4l2_ctrl *hblank;
++      struct v4l2_ctrl *vblank;
+       struct mutex lock;
+ };
+@@ -132,8 +136,6 @@ static const char * const imx290_test_pa
+ static const struct imx290_regval imx290_global_init_settings[] = {
+       { 0x3007, 0x00 },
+-      { 0x3018, 0x65 },
+-      { 0x3019, 0x04 },
+       { 0x301a, 0x00 },
+       { 0x303a, 0x0c },
+       { 0x3040, 0x00 },
+@@ -360,6 +362,7 @@ static const struct imx290_mode imx290_m
+               .width = 1920,
+               .height = 1080,
+               .hmax = 0x1130,
++              .vmax = 0x0465,
+               .link_freq_index = FREQ_INDEX_1080P,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+@@ -373,6 +376,7 @@ static const struct imx290_mode imx290_m
+               .width = 1280,
+               .height = 720,
+               .hmax = 0x19c8,
++              .vmax = 0x02ee,
+               .link_freq_index = FREQ_INDEX_720P,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+@@ -389,6 +393,7 @@ static const struct imx290_mode imx290_m
+               .width = 1920,
+               .height = 1080,
+               .hmax = 0x0898,
++              .vmax = 0x0465,
+               .link_freq_index = FREQ_INDEX_1080P,
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+@@ -402,6 +407,7 @@ static const struct imx290_mode imx290_m
+               .width = 1280,
+               .height = 720,
+               .hmax = 0x0ce4,
++              .vmax = 0x02ee,
+               .link_freq_index = FREQ_INDEX_720P,
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+@@ -543,6 +549,19 @@ static int imx290_set_hmax(struct imx290
+       return 0;
+ }
++static int imx290_set_vmax(struct imx290 *imx290, u32 val)
++{
++      u32 vmax = val + imx290->current_mode->height;
++      int ret;
++
++      ret = imx290_write_buffered_reg(imx290, IMX290_VMAX_LOW, 3,
++                                      vmax);
++      if (ret)
++              dev_err(imx290->dev, "Unable to write vmax\n");
++
++      return ret;
++}
++
+ /* Stop streaming */
+ static int imx290_stop_streaming(struct imx290 *imx290)
+ {
+@@ -574,6 +593,9 @@ static int imx290_set_ctrl(struct v4l2_c
+       case V4L2_CID_HBLANK:
+               ret = imx290_set_hmax(imx290, ctrl->val);
+               break;
++      case V4L2_CID_VBLANK:
++              ret = imx290_set_vmax(imx290, ctrl->val);
++              break;
+       case V4L2_CID_TEST_PATTERN:
+               if (ctrl->val) {
+                       imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
+@@ -736,6 +758,12 @@ static int imx290_set_fmt(struct v4l2_su
+                                                imx290->hmax_min - mode->width,
+                                                IMX290_HMAX_MAX - mode->width,
+                                                1, mode->hmax - mode->width);
++              if (imx290->vblank)
++                      __v4l2_ctrl_modify_range(imx290->vblank,
++                                               mode->vmax - mode->height,
++                                               IMX290_VMAX_MAX - mode->height,
++                                               1,
++                                               mode->vmax - mode->height);
+       }
+       *format = fmt->format;
+@@ -1148,6 +1176,12 @@ static int imx290_probe(struct i2c_clien
+                                          IMX290_HMAX_MAX - mode->width, 1,
+                                          mode->hmax - mode->width);
++      imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                                         V4L2_CID_VBLANK,
++                                         mode->vmax - mode->height,
++                                         IMX290_VMAX_MAX - mode->height, 1,
++                                         mode->vmax - mode->height);
++
+       imx290->link_freq =
+               v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+                                      V4L2_CID_LINK_FREQ,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0831-media-i2c-imx290-Add-exposure-control-to-the-driver.patch b/target/linux/bcm27xx/patches-5.4/950-0831-media-i2c-imx290-Add-exposure-control-to-the-driver.patch
new file mode 100644 (file)
index 0000000..86836dc
--- /dev/null
@@ -0,0 +1,93 @@
+From d6c85afca764dc32c3d7981867471fc820e07388 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 11 Jun 2020 18:19:13 +0100
+Subject: [PATCH] media: i2c: imx290: Add exposure control to the
+ driver.
+
+Adds support for V4L2_CID_EXPOSURE so that userspace can control
+the sensor exposure time.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 35 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -45,6 +45,10 @@ enum imx290_clk_index {
+ #define IMX290_HMAX_MIN_2LANE 4400 /* Min of 4400 pixels = 30fps */
+ #define IMX290_HMAX_MIN_4LANE 2200 /* Min of 2200 pixels = 60fps */
+ #define IMX290_HMAX_MAX 0xffff
++
++#define IMX290_EXPOSURE_MIN 2
++#define IMX290_EXPOSURE_STEP 1
++#define IMX290_EXPOSURE_LOW 0x3020
+ #define IMX290_PGCTRL 0x308c
+ #define IMX290_PHY_LANE_NUM 0x3407
+ #define IMX290_CSI_LANE_MODE 0x3443
+@@ -103,6 +107,7 @@ struct imx290 {
+       struct v4l2_ctrl *pixel_rate;
+       struct v4l2_ctrl *hblank;
+       struct v4l2_ctrl *vblank;
++      struct v4l2_ctrl *exposure;
+       struct mutex lock;
+ };
+@@ -529,6 +534,20 @@ static int imx290_set_gain(struct imx290
+       return ret;
+ }
++static int imx290_set_exposure(struct imx290 *imx290, u32 value)
++{
++      u32 exposure = (imx290->current_mode->height + imx290->vblank->val) -
++                                              value;
++      int ret;
++
++      ret = imx290_write_buffered_reg(imx290, IMX290_EXPOSURE_LOW, 3,
++                                      exposure);
++      if (ret)
++              dev_err(imx290->dev, "Unable to write exposure\n");
++
++      return ret;
++}
++
+ static int imx290_set_hmax(struct imx290 *imx290, u32 val)
+ {
+       u32 hmax = val + imx290->current_mode->width;
+@@ -590,6 +609,9 @@ static int imx290_set_ctrl(struct v4l2_c
+       case V4L2_CID_GAIN:
+               ret = imx290_set_gain(imx290, ctrl->val);
+               break;
++      case V4L2_CID_EXPOSURE:
++              ret = imx290_set_exposure(imx290, ctrl->val);
++              break;
+       case V4L2_CID_HBLANK:
+               ret = imx290_set_hmax(imx290, ctrl->val);
+               break;
+@@ -764,6 +786,12 @@ static int imx290_set_fmt(struct v4l2_su
+                                                IMX290_VMAX_MAX - mode->height,
+                                                1,
+                                                mode->vmax - mode->height);
++              if (imx290->exposure)
++                      __v4l2_ctrl_modify_range(imx290->exposure,
++                                               mode->vmax - mode->height,
++                                               mode->vmax - 4,
++                                               IMX290_EXPOSURE_STEP,
++                                               mode->vmax - 4);
+       }
+       *format = fmt->format;
+@@ -1182,6 +1210,13 @@ static int imx290_probe(struct i2c_clien
+                                          IMX290_VMAX_MAX - mode->height, 1,
+                                          mode->vmax - mode->height);
++      imx290->exposure = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                                           V4L2_CID_EXPOSURE,
++                                           IMX290_EXPOSURE_MIN,
++                                           mode->vmax - 4,
++                                           IMX290_EXPOSURE_STEP,
++                                           mode->vmax - 4);
++
+       imx290->link_freq =
+               v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+                                      V4L2_CID_LINK_FREQ,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0832-media-i2c-imx290-Add-H-and-V-flip-controls.patch b/target/linux/bcm27xx/patches-5.4/950-0832-media-i2c-imx290-Add-H-and-V-flip-controls.patch
new file mode 100644 (file)
index 0000000..b96807b
--- /dev/null
@@ -0,0 +1,83 @@
+From a6048e36f5e5d73a29d1f5096fc77286f8aa949d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 11 Jun 2020 18:34:16 +0100
+Subject: [PATCH] media: i2c: imx290: Add H and V flip controls
+
+The sensor supports horizontal and vertical flips, so support them
+through V4L2_CID_HFLIP and V4L2_CID_VFLIP.
+
+This sensor does NOT change the Bayer order when changing the
+direction of readout, therefore no special handling is required for
+that.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -34,6 +34,7 @@ enum imx290_clk_index {
+ #define IMX290_STANDBY 0x3000
+ #define IMX290_REGHOLD 0x3001
+ #define IMX290_XMSTA 0x3002
++#define IMX290_FLIP_WINMODE 0x3007
+ #define IMX290_FR_FDG_SEL 0x3009
+ #define IMX290_BLKLEVEL_LOW 0x300a
+ #define IMX290_BLKLEVEL_HIGH 0x300b
+@@ -107,6 +108,8 @@ struct imx290 {
+       struct v4l2_ctrl *pixel_rate;
+       struct v4l2_ctrl *hblank;
+       struct v4l2_ctrl *vblank;
++      struct v4l2_ctrl *hflip;
++      struct v4l2_ctrl *vflip;
+       struct v4l2_ctrl *exposure;
+       struct mutex lock;
+@@ -600,6 +603,7 @@ static int imx290_set_ctrl(struct v4l2_c
+       struct imx290 *imx290 = container_of(ctrl->handler,
+                                            struct imx290, ctrls);
+       int ret = 0;
++      u8 val;
+       /* V4L2 controls values will be applied only when power is already up */
+       if (!pm_runtime_get_if_in_use(imx290->dev))
+@@ -618,6 +622,16 @@ static int imx290_set_ctrl(struct v4l2_c
+       case V4L2_CID_VBLANK:
+               ret = imx290_set_vmax(imx290, ctrl->val);
+               break;
++      case V4L2_CID_HFLIP:
++      case V4L2_CID_VFLIP:
++              /* WINMODE is in bits [6:4], so need to read-modify-write */
++              ret = imx290_read_reg(imx290, IMX290_FLIP_WINMODE, &val);
++              if (ret)
++                      break;
++              val &= ~0x03;
++              val |= imx290->vflip->val | (imx290->hflip->val << 1);
++              ret = imx290_write_reg(imx290, IMX290_FLIP_WINMODE, val);
++              break;
+       case V4L2_CID_TEST_PATTERN:
+               if (ctrl->val) {
+                       imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
+@@ -924,6 +938,9 @@ static int imx290_set_stream(struct v4l2
+               imx290_stop_streaming(imx290);
+               pm_runtime_put(imx290->dev);
+       }
++      /* vflip and hflip cannot change during streaming */
++      __v4l2_ctrl_grab(imx290->vflip, enable);
++      __v4l2_ctrl_grab(imx290->hflip, enable);
+ unlock_and_return:
+@@ -1217,6 +1234,11 @@ static int imx290_probe(struct i2c_clien
+                                            IMX290_EXPOSURE_STEP,
+                                            mode->vmax - 4);
++      imx290->hflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                                        V4L2_CID_HFLIP, 0, 1, 1, 0);
++      imx290->vflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++                                        V4L2_CID_VFLIP, 0, 1, 1, 0);
++
+       imx290->link_freq =
+               v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+                                      V4L2_CID_LINK_FREQ,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0833-media-dt-bindings-media-i2c-Add-mono-version-to-IMX2.patch b/target/linux/bcm27xx/patches-5.4/950-0833-media-dt-bindings-media-i2c-Add-mono-version-to-IMX2.patch
new file mode 100644 (file)
index 0000000..50c93f0
--- /dev/null
@@ -0,0 +1,36 @@
+From 05ba3df09751ff516de5d862c98f5a979b51bb56 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 16:52:14 +0100
+Subject: [PATCH] media: dt-bindings: media: i2c: Add mono version to
+ IMX290 bindings
+
+The IMX290 module is available as either monochrome or colour and
+the variant is not detectable at runtime.
+
+Add a new compatible string for the monochrome version.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ Documentation/devicetree/bindings/media/i2c/imx290.txt | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/Documentation/devicetree/bindings/media/i2c/imx290.txt
++++ b/Documentation/devicetree/bindings/media/i2c/imx290.txt
+@@ -1,13 +1,14 @@
+ * Sony IMX290 1/2.8-Inch CMOS Image Sensor
+ The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with
+-Square Pixel for Color Cameras. It is programmable through I2C and 4-wire
+-interfaces. The sensor output is available via CMOS logic parallel SDR output,
++Square Pixel for Color or Monochrome Cameras. It is programmable through I2C
++and 4-wire interfaces.
++The sensor output is available via CMOS logic parallel SDR output,
+ Low voltage LVDS DDR output and CSI-2 serial data output. The CSI-2 bus is the
+ default. No bindings have been defined for the other busses.
+ Required Properties:
+-- compatible: Should be "sony,imx290"
++- compatible: Should be "sony,imx290", or "sony,imx290-mono"
+ - reg: I2C bus address of the device
+ - clocks: Reference to the xclk clock.
+ - clock-names: Should be "xclk".
diff --git a/target/linux/bcm27xx/patches-5.4/950-0834-media-i2c-imx290-Add-support-for-the-mono-sensor-var.patch b/target/linux/bcm27xx/patches-5.4/950-0834-media-i2c-imx290-Add-support-for-the-mono-sensor-var.patch
new file mode 100644 (file)
index 0000000..f75a220
--- /dev/null
@@ -0,0 +1,185 @@
+From c9f918319593861c4975b229579def5fbd637ad9 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 17:03:11 +0100
+Subject: [PATCH] media : i2c: imx290: Add support for the mono
+ sensor variant.
+
+The IMX290 module is available as either mono or colour (Bayer).
+
+Update the driver so that it can advertise the correct mono
+formats instead of the colour ones.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 58 +++++++++++++++++++++++++++-----------
+ 1 file changed, 41 insertions(+), 17 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -1,10 +1,12 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * Sony IMX290/327 CMOS Image Sensor Driver
++ * Sony IMX290 & IMX327 CMOS Image Sensor Driver
+  *
+  * The IMX290 and IMX327 are very similar 1920x1080 1/2.8 CMOS image sensors.
+- * IMX327 can support up to 60fps, whilst IMX290 support up to 120fps (only
+- * 10bit and when connected over 4 CSI-2 lanes).
++ * IMX327 can support up to 60fps, whilst IMX290 can support up to 120fps, but
++ * only 10bit and when connected over 4 CSI-2 lanes.
++ * The modules don't appear to have a mechanism to identify whether the mono or
++ * colour variant is connected, therefore it is done via compatible string.
+  *
+  * Copyright (C) 2019 FRAMOS GmbH.
+  *
+@@ -17,6 +19,7 @@
+ #include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+ #include <linux/module.h>
++#include <linux/of_device.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+@@ -95,6 +98,8 @@ struct imx290 {
+       u8 bpp;
+       u16 hmax_min;
++      const struct imx290_pixfmt *formats;
++
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+       struct v4l2_mbus_framefmt current_format;
+@@ -120,11 +125,18 @@ struct imx290_pixfmt {
+       u8 bpp;
+ };
+-static const struct imx290_pixfmt imx290_formats[] = {
++#define IMX290_NUM_FORMATS 2
++
++static const struct imx290_pixfmt imx290_colour_formats[IMX290_NUM_FORMATS] = {
+       { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
+       { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
+ };
++static const struct imx290_pixfmt imx290_mono_formats[IMX290_NUM_FORMATS] = {
++      { MEDIA_BUS_FMT_Y10_1X10, 10 },
++      { MEDIA_BUS_FMT_Y12_1X12, 12 },
++};
++
+ static const struct regmap_config imx290_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 8,
+@@ -671,10 +683,12 @@ static int imx290_enum_mbus_code(struct
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_mbus_code_enum *code)
+ {
+-      if (code->index >= ARRAY_SIZE(imx290_formats))
++      const struct imx290 *imx290 = to_imx290(sd);
++
++      if (code->index >= IMX290_NUM_FORMATS)
+               return -EINVAL;
+-      code->code = imx290_formats[code->index].code;
++      code->code = imx290->formats[code->index].code;
+       return 0;
+ }
+@@ -686,8 +700,8 @@ static int imx290_enum_frame_size(struct
+       const struct imx290 *imx290 = to_imx290(sd);
+       const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
+-      if ((fse->code != imx290_formats[0].code) &&
+-          (fse->code != imx290_formats[1].code))
++      if (fse->code != imx290->formats[0].code &&
++          fse->code != imx290->formats[1].code)
+               return -EINVAL;
+       if (fse->index >= imx290_modes_num(imx290))
+@@ -765,14 +779,14 @@ static int imx290_set_fmt(struct v4l2_su
+       fmt->format.width = mode->width;
+       fmt->format.height = mode->height;
+-      for (i = 0; i < ARRAY_SIZE(imx290_formats); i++)
+-              if (imx290_formats[i].code == fmt->format.code)
++      for (i = 0; i < IMX290_NUM_FORMATS; i++)
++              if (imx290->formats[i].code == fmt->format.code)
+                       break;
+-      if (i >= ARRAY_SIZE(imx290_formats))
++      if (i >= IMX290_NUM_FORMATS)
+               i = 0;
+-      fmt->format.code = imx290_formats[i].code;
++      fmt->format.code = imx290->formats[i].code;
+       fmt->format.field = V4L2_FIELD_NONE;
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+@@ -780,7 +794,7 @@ static int imx290_set_fmt(struct v4l2_su
+       } else {
+               format = &imx290->current_format;
+               imx290->current_mode = mode;
+-              imx290->bpp = imx290_formats[i].bpp;
++              imx290->bpp = imx290->formats[i].bpp;
+               if (imx290->link_freq)
+                       __v4l2_ctrl_s_ctrl(imx290->link_freq,
+@@ -835,6 +849,7 @@ static int imx290_write_current_format(s
+       switch (imx290->current_format.code) {
+       case MEDIA_BUS_FMT_SRGGB10_1X10:
++      case MEDIA_BUS_FMT_Y10_1X10:
+               ret = imx290_set_register_array(imx290, imx290_10bit_settings,
+                                               ARRAY_SIZE(
+                                                       imx290_10bit_settings));
+@@ -844,6 +859,7 @@ static int imx290_write_current_format(s
+               }
+               break;
+       case MEDIA_BUS_FMT_SRGGB12_1X12:
++      case MEDIA_BUS_FMT_Y12_1X12:
+               ret = imx290_set_register_array(imx290, imx290_12bit_settings,
+                                               ARRAY_SIZE(
+                                                       imx290_12bit_settings));
+@@ -1091,6 +1107,12 @@ static s64 imx290_check_link_freqs(const
+       return 0;
+ }
++static const struct of_device_id imx290_of_match[] = {
++      { .compatible = "sony,imx290", .data = imx290_colour_formats },
++      { .compatible = "sony,imx290-mono", .data = imx290_mono_formats },
++      { /* sentinel */ }
++};
++
+ static int imx290_probe(struct i2c_client *client)
+ {
+       struct device *dev = &client->dev;
+@@ -1099,6 +1121,7 @@ static int imx290_probe(struct i2c_clien
+       struct v4l2_fwnode_endpoint ep = {
+               .bus_type = V4L2_MBUS_CSI2_DPHY
+       };
++      const struct of_device_id *match;
+       const struct imx290_mode *mode;
+       struct imx290 *imx290;
+       s64 fq;
+@@ -1115,6 +1138,11 @@ static int imx290_probe(struct i2c_clien
+               return -ENODEV;
+       }
++      match = of_match_device(imx290_of_match, dev);
++      if (!match)
++              return -ENODEV;
++      imx290->formats = (const struct imx290_pixfmt *)match->data;
++
+       endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
+       if (!endpoint) {
+               dev_err(dev, "Endpoint node not found\n");
+@@ -1330,10 +1358,6 @@ static int imx290_remove(struct i2c_clie
+       return 0;
+ }
+-static const struct of_device_id imx290_of_match[] = {
+-      { .compatible = "sony,imx290" },
+-      { /* sentinel */ }
+-};
+ MODULE_DEVICE_TABLE(of, imx290_of_match);
+ static struct i2c_driver imx290_i2c_driver = {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0835-media-i2c-imx290-Switch-set_hmax-to-use-imx290_write.patch b/target/linux/bcm27xx/patches-5.4/950-0835-media-i2c-imx290-Switch-set_hmax-to-use-imx290_write.patch
new file mode 100644 (file)
index 0000000..7819e70
--- /dev/null
@@ -0,0 +1,43 @@
+From 970208edb92b04eaa329c666e2e91717984c28b6 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 26 Jun 2020 18:11:49 +0100
+Subject: [PATCH] media: i2c: imx290: Switch set_hmax to use
+ imx290_write_buffered_reg
+
+imx290_set_hmax was using two independent writes to set up hmax,
+when all other multi-register writes were using imx290_write_buffered_reg
+which claims the group hold first.
+
+Switch imx290_set_hmax to using imx290_write_buffered_reg too.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 15 ++++-----------
+ 1 file changed, 4 insertions(+), 11 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -568,19 +568,12 @@ static int imx290_set_hmax(struct imx290
+       u32 hmax = val + imx290->current_mode->width;
+       int ret;
+-      ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (hmax & 0xff));
+-      if (ret) {
++      ret = imx290_write_buffered_reg(imx290, IMX290_HMAX_LOW, 2,
++                                      hmax);
++      if (ret)
+               dev_err(imx290->dev, "Error setting HMAX register\n");
+-              return ret;
+-      }
+-      ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((hmax >> 8) & 0xff));
+-      if (ret) {
+-              dev_err(imx290->dev, "Error setting HMAX register\n");
+-              return ret;
+-      }
+-
+-      return 0;
++      return ret;
+ }
+ static int imx290_set_vmax(struct imx290 *imx290, u32 val)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0836-dtoverlays-Add-an-overlay-for-the-Sony-IMX290-image-.patch b/target/linux/bcm27xx/patches-5.4/950-0836-dtoverlays-Add-an-overlay-for-the-Sony-IMX290-image-.patch
new file mode 100644 (file)
index 0000000..f64db00
--- /dev/null
@@ -0,0 +1,236 @@
+From 57250281004e141dff4662d1abb3f31982ec01ee Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 19 May 2020 13:35:17 +0100
+Subject: [PATCH] dtoverlays: Add an overlay for the Sony IMX290
+ image sensor
+
+Adds an overlay to configure the IMX290 image sensor.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  16 ++
+ arch/arm/boot/dts/overlays/imx290-overlay.dts |  32 ++++
+ .../boot/dts/overlays/imx290_327-overlay.dtsi | 145 ++++++++++++++++++
+ 4 files changed, 194 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/imx290-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -85,6 +85,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       i2s-gpio28-31.dtbo \
+       ilitek251x.dtbo \
+       imx219.dtbo \
++      imx290.dtbo \
+       imx477.dtbo \
+       iqaudio-codec.dtbo \
+       iqaudio-dac.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1430,6 +1430,22 @@ Load:   dtoverlay=imx219
+ Params: <None>
++Name:   imx290
++Info:   Sony IMX290 camera module.
++        Uses Unicam 1, which is the standard camera connector on most Pi
++        variants. NB This currently uses 4 CSI2 data lanes and therefore will
++        only work on a CM.
++Load:   dtoverlay=imx290,<param>
++Params: 4lane                   Enable 4 CSI2 lanes. This requires a Compute
++                                Module (1, 3, or 4).
++        clock-frequency         Sets the clock frequency to match that used on
++                                the board.
++                                Modules from Vision Components use 37.125MHz
++                                (the default), whilst those from Innomaker use
++                                74.25MHz.
++        mono                    Denote that the module is a mono sensor.
++
++
+ Name:   imx477
+ Info:   Sony IMX477 camera module.
+         Uses Unicam 1, which is the standard camera connector on most Pi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/imx290-overlay.dts
+@@ -0,0 +1,32 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Definitions for IMX290 camera module on VC I2C bus
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++#include "imx290_327-overlay.dtsi"
++
++/{
++      compatible = "brcm,bcm2835";
++
++      // Fragment numbers deliberately high to avoid conflicts with the
++      // included imx290_327 overlay file.
++
++      fragment@101 {
++              target = <&imx290>;
++              __overlay__ {
++                      compatible = "sony,imx290";
++              };
++      };
++
++      fragment@102 {
++              target = <&imx290>;
++              __dormant__ {
++                      compatible = "sony,imx290-mono";
++              };
++      };
++
++      __overrides__ {
++              mono = <0>, "-101+102";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi
+@@ -0,0 +1,145 @@
++// 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
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c_csi_dsi>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      imx290: imx290@1a {
++                              reg = <0x1a>;
++                              status = "okay";
++
++                              clocks = <&imx290_clk>;
++                              clock-names = "xclk";
++                              clock-frequency = <37125000>;
++
++                              vdda-supply = <&imx290_vdda>;   /* 2.8v */
++                              vdddo-supply = <&imx290_vdddo>; /* 1.8v */
++                              vddd-supply = <&imx290_vddd>;   /* 1.5v */
++
++                              port {
++                                      imx290_0: endpoint {
++                                              remote-endpoint = <&csi1_ep>;
++                                              clock-lanes = <0>;
++                                      };
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&csi1>;
++              __overlay__ {
++                      status = "okay";
++
++                      port {
++                              csi1_ep: endpoint {
++                                      remote-endpoint = <&imx290_0>;
++                              };
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c0if>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@3 {
++              target-path="/";
++              __overlay__ {
++                      imx290_vdda: fixedregulator@0 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "imx290_vdda";
++                              regulator-min-microvolt = <2800000>;
++                              regulator-max-microvolt = <2800000>;
++                              gpio = <&gpio 41 GPIO_ACTIVE_HIGH>;
++                              enable-active-high;
++                      };
++                      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>;
++                      };
++              };
++      };
++
++      fragment@4 {
++              target = <&i2c0mux>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@5 {
++              target-path="/__overrides__";
++              __overlay__ {
++                      cam0-pwdn-ctrl = <&imx290_vdda>,"gpio:0";
++                      cam0-pwdn      = <&imx290_vdda>,"gpio:4";
++              };
++      };
++
++      fragment@6 {
++              target = <&imx290_0>;
++              __overlay__ {
++                      data-lanes = <1 2>;
++                      link-frequencies =
++                              /bits/ 64 <445500000 297000000>;
++              };
++      };
++
++      fragment@7 {
++              target = <&imx290_0>;
++              __dormant__ {
++                      data-lanes = <1 2 3 4>;
++                      link-frequencies =
++                              /bits/ 64 <222750000 148500000>;
++              };
++      };
++
++      fragment@8 {
++              target = <&csi1_ep>;
++              __overlay__ {
++                      data-lanes = <1 2>;
++              };
++      };
++
++      fragment@9 {
++              target = <&csi1_ep>;
++              __dormant__ {
++                      data-lanes = <1 2 3 4>;
++              };
++      };
++
++      __overrides__ {
++              4lane = <0>, "-6+7-8+9";
++              clock-frequency = <&imx290_clk>,"clock-frequency:0",
++                                <&imx290>,"clock-frequency:0";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0837-vc4_hdmi-Set-HD_CTL_WHOLSMP-and-HD_CTL_CHALIGN_SET.patch b/target/linux/bcm27xx/patches-5.4/950-0837-vc4_hdmi-Set-HD_CTL_WHOLSMP-and-HD_CTL_CHALIGN_SET.patch
new file mode 100644 (file)
index 0000000..859a560
--- /dev/null
@@ -0,0 +1,38 @@
+From c69a53be3b5f6f7cba0ac6a5461d4f342f7e9c41 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Tue, 23 Jun 2020 18:37:01 +0100
+Subject: [PATCH] vc4_hdmi: Set HD_CTL_WHOLSMP and HD_CTL_CHALIGN_SET
+
+Symptom is random switching of speakers when using multichannel.
+
+Repeatedly running speakertest -c8 occasionally starts with
+channels jumbled. This is fixed with HD_CTL_WHOLSMP.
+
+The other bit looks beneficial and apears harmless in testing so
+I'd suggest adding it too.
+
+Documentation says: HD_CTL_WHILSMP_SET
+Wait for whole sample. When this bit is set MAI transmit will start
+only when there is at least one whole sample available in the fifo.
+
+Documentation says: HD_CTL_CHALIGN_SET
+Channel Align When Overflow. This bit is used to realign the audio channels in case of an overflow.
+If this bit is set, after the detection of an overflow, equal amount of dummy words to the missing
+words will be written to fifo, filling up the broken sample and maintaining alignment.
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -1002,6 +1002,8 @@ static int vc4_hdmi_audio_trigger(struct
+               HDMI_WRITE(HDMI_MAI_CTL,
+                        VC4_SET_FIELD(vc4_hdmi->audio.channels,
+                                      VC4_HD_MAI_CTL_CHNUM) |
++                                     VC4_HD_MAI_CTL_WHOLSMP |
++                                     VC4_HD_MAI_CTL_CHALIGN |
+                        VC4_HD_MAI_CTL_ENABLE);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
diff --git a/target/linux/bcm27xx/patches-5.4/950-0838-staging-vc04_services-isp-Fixup-g-s_selection-implem.patch b/target/linux/bcm27xx/patches-5.4/950-0838-staging-vc04_services-isp-Fixup-g-s_selection-implem.patch
new file mode 100644 (file)
index 0000000..fd24c87
--- /dev/null
@@ -0,0 +1,129 @@
+From 7ec008222fcb4682fa2cfdbb62e657bf98950ec5 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Tue, 19 May 2020 15:56:47 +0100
+Subject: [PATCH] staging: vc04_services: isp: Fixup g/s_selection
+ implementation
+
+Add V4L2_SEL_TGT_CROP_DEFAULT and V4L2_SEL_TGT_CROP_BOUND targets.
+Disable the appropriate ioctls for the meta capture nodes - this now
+passes v4l2-compliance tests.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ .../bcm2835-isp/bcm2835-v4l2-isp.c            | 84 ++++++++++++-------
+ 1 file changed, 55 insertions(+), 29 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -1006,15 +1006,32 @@ static int bcm2835_isp_node_s_selection(
+       if (!s->r.width || !s->r.height)
+               return -EINVAL;
+-      /* Adjust the crop window if goes outside the frame dimensions. */
+-      s->r.left = min((unsigned int)max(s->r.left, 0),
+-                      node->q_data.width - MIN_DIM);
+-      s->r.top = min((unsigned int)max(s->r.top, 0),
+-                     node->q_data.height - MIN_DIM);
+-      s->r.width = max(min(s->r.width, node->q_data.width - s->r.left),
+-                       MIN_DIM);
+-      s->r.height = max(min(s->r.height, node->q_data.height - s->r.top),
+-                        MIN_DIM);
++      /* We can only set crop on the input. */
++      switch (s->target) {
++      case V4L2_SEL_TGT_CROP:
++              /*
++               * Adjust the crop window if it goes outside of the frame
++               * dimensions.
++               */
++              s->r.left = min((unsigned int)max(s->r.left, 0),
++                              node->q_data.width - MIN_DIM);
++              s->r.top = min((unsigned int)max(s->r.top, 0),
++                             node->q_data.height - MIN_DIM);
++              s->r.width = max(min(s->r.width,
++                                   node->q_data.width - s->r.left), MIN_DIM);
++              s->r.height = max(min(s->r.height,
++                                    node->q_data.height - s->r.top), MIN_DIM);
++              break;
++      case V4L2_SEL_TGT_CROP_DEFAULT:
++              /* Default (i.e. no) crop window. */
++              s->r.left = 0;
++              s->r.top = 0;
++              s->r.width = node->q_data.width;
++              s->r.height = node->q_data.height;
++              break;
++      default:
++              return -EINVAL;
++      }
+       crop.rect.x = s->r.left;
+       crop.rect.y = s->r.top;
+@@ -1029,33 +1046,40 @@ static int bcm2835_isp_node_s_selection(
+ static int bcm2835_isp_node_g_selection(struct file *file, void *fh,
+                                       struct v4l2_selection *s)
+ {
++      struct mmal_parameter_crop crop;
+       struct bcm2835_isp_node *node = video_drvdata(file);
+-      struct bcm2835_isp_dev *dev = node_get_dev(node);
+       struct vchiq_mmal_port *port = get_port_data(node);
+-      struct mmal_parameter_crop crop;
++      struct bcm2835_isp_dev *dev = node_get_dev(node);
+       u32 crop_size = sizeof(crop);
+       int ret;
+-      /* This return value is required for V4L2 compliance. */
+-      if (node_is_stats(node))
+-              return -ENOTTY;
+-
+       /* We can only return out an input crop. */
+-      if (s->target != V4L2_SEL_TGT_CROP)
+-              return -EINVAL;
+-
+-      ret = vchiq_mmal_port_parameter_get(dev->mmal_instance, port,
+-                                          MMAL_PARAMETER_CROP,
+-                                          &crop, &crop_size);
+-      if (!ret)
+-              return -EINVAL;
+-
+-      s->r.left = crop.rect.x;
+-      s->r.top = crop.rect.y;
+-      s->r.width = crop.rect.width;
+-      s->r.height = crop.rect.height;
++      switch (s->target) {
++      case V4L2_SEL_TGT_CROP:
++              ret = vchiq_mmal_port_parameter_get(dev->mmal_instance, port,
++                                                  MMAL_PARAMETER_CROP,
++                                                  &crop, &crop_size);
++              if (!ret) {
++                      s->r.left = crop.rect.x;
++                      s->r.top = crop.rect.y;
++                      s->r.width = crop.rect.width;
++                      s->r.height = crop.rect.height;
++              }
++              break;
++      case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
++              /* Default (i.e. no) crop window. */
++              s->r.left = 0;
++              s->r.top = 0;
++              s->r.width = node->q_data.width;
++              s->r.height = node->q_data.height;
++              ret = 0;
++              break;
++      default:
++              ret =  -EINVAL;
++      }
+-      return 0;
++      return ret;
+ }
+ static int bcm3285_isp_subscribe_event(struct v4l2_fh *fh,
+@@ -1218,6 +1242,8 @@ static int register_node(struct bcm2835_
+               node->vfl_dir = VFL_DIR_RX;
+               node->name = "stats";
+               v4l2_disable_ioctl(&node->vfd, VIDIOC_S_CTRL);
++              v4l2_disable_ioctl(&node->vfd, VIDIOC_S_SELECTION);
++              v4l2_disable_ioctl(&node->vfd, VIDIOC_G_SELECTION);
+               break;
+       }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0839-staging-vc04_services-isp-Reorder-operations-during-.patch b/target/linux/bcm27xx/patches-5.4/950-0839-staging-vc04_services-isp-Reorder-operations-during-.patch
new file mode 100644 (file)
index 0000000..3300ed4
--- /dev/null
@@ -0,0 +1,92 @@
+From af066bde5a442efd50868ffed1aad30190400c91 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Tue, 19 May 2020 15:57:08 +0100
+Subject: [PATCH] staging: vc04_services: isp: Reorder operations
+ during device probe
+
+Register the video node at the end of the probe, swapping order with
+registering the controls.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ .../bcm2835-isp/bcm2835-v4l2-isp.c            | 48 ++++++++++++-------
+ 1 file changed, 32 insertions(+), 16 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -1295,21 +1295,6 @@ static int register_node(struct bcm2835_
+       }
+       node->queue_init = true;
+-      /* Define the device names */
+-      snprintf(vfd->name, sizeof(node->vfd.name), "%s-%s%d", BCM2835_ISP_NAME,
+-               node->name, node->id);
+-
+-      ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr + index);
+-      if (ret) {
+-              v4l2_err(&dev->v4l2_dev,
+-                       "Failed to register video %s[%d] device node\n",
+-                       node->name, node->id);
+-              return ret;
+-      }
+-
+-      node->registered = true;
+-      video_set_drvdata(vfd, node);
+-
+       /* Set some controls and defaults, but only on the VIDEO_OUTPUT node. */
+       if (node_is_output(node)) {
+               unsigned int i;
+@@ -1324,7 +1309,12 @@ static int register_node(struct bcm2835_
+                       .step           = 1,
+               };
+-              v4l2_ctrl_handler_init(&dev->ctrl_handler, 4);
++              ret = v4l2_ctrl_handler_init(&dev->ctrl_handler, 12);
++              if (ret) {
++                      v4l2_err(&dev->v4l2_dev, "ctrl_handler init failed (%d)\n",
++                               ret);
++                      return ret;
++              }
+               dev->r_gain = 1000;
+               dev->b_gain = 1000;
+@@ -1350,13 +1340,39 @@ static int register_node(struct bcm2835_
+               }
+               node->vfd.ctrl_handler = &dev->ctrl_handler;
++              if (dev->ctrl_handler.error) {
++                      ret = dev->ctrl_handler.error;
++                      v4l2_err(&dev->v4l2_dev, "controls init failed (%d)\n",
++                               ret);
++                      v4l2_ctrl_handler_free(&dev->ctrl_handler);
++                      goto ctrl_cleanup;
++              }
+       }
++      /* Define the device names */
++      snprintf(vfd->name, sizeof(node->vfd.name), "%s-%s%d", BCM2835_ISP_NAME,
++               node->name, node->id);
++
++      ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr + index);
++      if (ret) {
++              v4l2_err(&dev->v4l2_dev,
++                       "Failed to register video %s[%d] device node\n",
++                       node->name, node->id);
++              goto ctrl_cleanup;
++      }
++
++      node->registered = true;
++      video_set_drvdata(vfd, node);
++
+       v4l2_info(&dev->v4l2_dev,
+                 "Device node %s[%d] registered as /dev/video%d\n",
+                 node->name, node->id, vfd->num);
+       return 0;
++
++ctrl_cleanup:
++      v4l2_ctrl_handler_free(&dev->ctrl_handler);
++      return ret;
+ }
+ /* Unregister one of the /dev/video<N> nodes associated with the ISP. */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0840-uapi-bcm2835-isp-Fixups-for-bcm2835-isp-uapi-structu.patch b/target/linux/bcm27xx/patches-5.4/950-0840-uapi-bcm2835-isp-Fixups-for-bcm2835-isp-uapi-structu.patch
new file mode 100644 (file)
index 0000000..e3ee0d9
--- /dev/null
@@ -0,0 +1,34 @@
+From b1a21b378ea123942db1d07007a040c5e89b23aa Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Tue, 19 May 2020 15:57:23 +0100
+Subject: [PATCH] uapi: bcm2835-isp: Fixups for bcm2835-isp uapi
+ structures
+
+Rename pad_[] to padding[].
+struct bcm2835_isp_rational.den is now unsigned.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ include/uapi/linux/bcm2835-isp.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/include/uapi/linux/bcm2835-isp.h
++++ b/include/uapi/linux/bcm2835-isp.h
+@@ -46,7 +46,7 @@
+  */
+ struct bcm2835_isp_rational {
+       __s32 num;
+-      __s32 den;
++      __u32 den;
+ };
+ /**
+@@ -140,7 +140,7 @@ struct bcm2835_isp_black_level {
+       __u16 black_level_r;
+       __u16 black_level_g;
+       __u16 black_level_b;
+-      __u8 pad_[2]; /* Unused */
++      __u8 padding[2]; /* Unused */
+ };
+ /**
diff --git a/target/linux/bcm27xx/patches-5.4/950-0841-ARM-dts-Add-Bluetooth-nodes-for-Raspberry-Pi.patch b/target/linux/bcm27xx/patches-5.4/950-0841-ARM-dts-Add-Bluetooth-nodes-for-Raspberry-Pi.patch
new file mode 100644 (file)
index 0000000..fd66e65
--- /dev/null
@@ -0,0 +1,283 @@
+From c46a59c99e53ab41096afcf7f7879bb12769346b Mon Sep 17 00:00:00 2001
+From: Maxim Mikityanskiy <maxtram95@gmail.com>
+Date: Sat, 27 Jun 2020 13:08:26 +0300
+Subject: [PATCH] ARM: dts: Add Bluetooth nodes for Raspberry Pi
+
+Add device tree nodes for Bluetooth on supported Raspberry Pi boards.
+It's disabled by default and can be enabled by `krnbt=on` dtparam. It's
+an alternative way of configuring Bluetooth, as compared to hciattach or
+btattach. When the dtparam is enabled, the Bluetooth driver is probed
+automatically and doesn't require any additional bring-up scripts.
+
+Note that Raspberry Pi 3 B rev 1.2 doesn't have the required hardware
+flow control pins of UART0 connected to the Bluetooth module, so the
+user should decrease the baudrate by passing `krnbt_baudrate=921600`
+dtparam to make it more stable. It resembles the behavior of the btuart
+script from Raspbian.
+
+The miniuart-bt overlay was modified to support Bluetooth probing with
+device tree, too. It's disabled by default and can be enabled by
+`krnbt=on` parameter of the miniuart-bt overlay.
+
+Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+---
+ arch/arm/boot/dts/bcm2708-rpi-bt.dtsi         | 26 +++++++++++++++++++
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts      |  1 +
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts    |  1 +
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts         |  1 +
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts         |  3 +--
+ arch/arm/boot/dts/bcm271x-rpi-bt.dtsi         | 26 +++++++++++++++++++
+ arch/arm/boot/dts/overlays/README             | 12 +++++++--
+ .../boot/dts/overlays/disable-bt-overlay.dts  | 13 ++++++++--
+ .../boot/dts/overlays/miniuart-bt-overlay.dts | 21 ++++++++++++---
+ 9 files changed, 94 insertions(+), 10 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm2708-rpi-bt.dtsi
+ create mode 100644 arch/arm/boot/dts/bcm271x-rpi-bt.dtsi
+
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2708-rpi-bt.dtsi
+@@ -0,0 +1,26 @@
++// SPDX-License-Identifier: GPL-2.0
++
++&uart0 {
++      bt: bluetooth {
++              compatible = "brcm,bcm43438-bt";
++              max-speed = <3000000>;
++              shutdown-gpios = <&gpio 45 GPIO_ACTIVE_HIGH>;
++              status = "disabled";
++      };
++};
++
++&uart1 {
++      minibt: bluetooth {
++              compatible = "brcm,bcm43438-bt";
++              max-speed = <460800>;
++              shutdown-gpios = <&gpio 45 GPIO_ACTIVE_HIGH>;
++              status = "disabled";
++      };
++};
++
++/ {
++      __overrides__ {
++              krnbt = <&bt>,"status";
++              krnbt_baudrate = <&bt>,"max-speed:0";
++      };
++};
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -4,6 +4,7 @@
+ #include "bcm2708-rpi.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ #include "bcm283x-rpi-i2c0mux_0_28.dtsi"
++#include "bcm2708-rpi-bt.dtsi"
+ / {
+       compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -5,6 +5,7 @@
+ #include "bcm283x-rpi-lan7515.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ #include "bcm283x-rpi-i2c0mux_0_44.dtsi"
++#include "bcm271x-rpi-bt.dtsi"
+ / {
+       compatible = "raspberrypi,3-model-b-plus", "brcm,bcm2837";
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -5,6 +5,7 @@
+ #include "bcm283x-rpi-smsc9514.dtsi"
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ #include "bcm283x-rpi-i2c0mux_0_44.dtsi"
++#include "bcm271x-rpi-bt.dtsi"
+ / {
+       compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -182,6 +182,7 @@
+ // Downstream rpi- changes
+ #include "bcm270x.dtsi"
++#include "bcm271x-rpi-bt.dtsi"
+ / {
+       soc {
+@@ -250,8 +251,6 @@
+ &uart0 {
+       pinctrl-0 = <&uart0_pins &bt_pins>;
+       status = "okay";
+-
+-      /delete-node/ bluetooth;
+ };
+ &uart1 {
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm271x-rpi-bt.dtsi
+@@ -0,0 +1,26 @@
++// SPDX-License-Identifier: GPL-2.0
++
++&uart0 {
++      bt: bluetooth {
++              compatible = "brcm,bcm43438-bt";
++              max-speed = <3000000>;
++              shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
++              status = "disabled";
++      };
++};
++
++&uart1 {
++      minibt: bluetooth {
++              compatible = "brcm,bcm43438-bt";
++              max-speed = <460800>;
++              shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
++              status = "disabled";
++      };
++};
++
++/ {
++      __overrides__ {
++              krnbt = <&bt>,"status";
++              krnbt_baudrate = <&bt>,"max-speed:0";
++      };
++};
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -162,6 +162,13 @@ Params:
+         i2s                     Set to "on" to enable the i2s interface
+                                 (default "off")
++        krnbt                   Set to "on" to enable autoprobing of Bluetooth
++                                driver without need of hciattach/btattach
++                                (default "off")
++
++        krnbt_baudrate          Set the baudrate of the PL011 UART when used
++                                with krnbt=on
++
+         spi                     Set to "on" to enable the spi interfaces
+                                 (default "off")
+@@ -1764,8 +1771,9 @@ Info:   Switch the onboard Bluetooth fun
+         in which case use /dev/serial1 instead because it will always be
+         correct. Furthermore, you must also set core_freq and core_freq_min to
+         the same value in config.txt or the miniuart will not work.
+-Load:   dtoverlay=miniuart-bt
+-Params: <None>
++Load:   dtoverlay=miniuart-bt,<param>=<val>
++Params: krnbt                   Set to "on" to enable autoprobing of Bluetooth
++                                driver without need of hciattach/btattach
+ Name:   mmc
+--- a/arch/arm/boot/dts/overlays/disable-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/disable-bt-overlay.dts
+@@ -8,6 +8,8 @@
+        sudo systemctl disable hciuart
+ */
++#include <dt-bindings/gpio/gpio.h>
++
+ /{
+       compatible = "brcm,bcm2835";
+@@ -28,6 +30,13 @@
+       };
+       fragment@2 {
++              target = <&bt>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@3 {
+               target = <&uart0_pins>;
+               __overlay__ {
+                       brcm,pins;
+@@ -36,7 +45,7 @@
+               };
+       };
+-      fragment@3 {
++      fragment@4 {
+               target = <&bt_pins>;
+               __overlay__ {
+                       brcm,pins;
+@@ -45,7 +54,7 @@
+               };
+       };
+-      fragment@4 {
++      fragment@5 {
+               target-path = "/aliases";
+               __overlay__ {
+                       serial0 = "/soc/serial@7e201000";
+--- a/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
+@@ -15,6 +15,8 @@
+    this overlay is used.
+ */
++#include <dt-bindings/gpio/gpio.h>
++
+ /{
+       compatible = "brcm,bcm2835";
+@@ -28,6 +30,13 @@
+       };
+       fragment@1 {
++              target = <&bt>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
+               target = <&uart1>;
+               __overlay__ {
+                       pinctrl-names = "default";
+@@ -36,7 +45,7 @@
+               };
+       };
+-      fragment@2 {
++      fragment@3 {
+               target = <&uart0_pins>;
+               __overlay__ {
+                       brcm,pins;
+@@ -45,7 +54,7 @@
+               };
+       };
+-      fragment@3 {
++      fragment@4 {
+               target = <&uart1_pins>;
+               __overlay__ {
+                       brcm,pins = <32 33>;
+@@ -54,7 +63,7 @@
+               };
+       };
+-      fragment@4 {
++      fragment@5 {
+               target = <&gpio>;
+               __overlay__ {
+                       fake_bt_cts: fake_bt_cts {
+@@ -64,11 +73,15 @@
+               };
+       };
+-      fragment@5 {
++      fragment@6 {
+               target-path = "/aliases";
+               __overlay__ {
+                       serial0 = "/soc/serial@7e201000";
+                       serial1 = "/soc/serial@7e215040";
+               };
+       };
++
++      __overrides__ {
++              krnbt = <&minibt>,"status";
++      };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0842-drm-vc4-Allow-interlaced-HDMI-modes-from-FKMS.patch b/target/linux/bcm27xx/patches-5.4/950-0842-drm-vc4-Allow-interlaced-HDMI-modes-from-FKMS.patch
new file mode 100644 (file)
index 0000000..8cb8531
--- /dev/null
@@ -0,0 +1,37 @@
+From 354bf89fd678a6da6256a6ac37440c27c3b62e80 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 30 Jun 2020 18:04:13 +0100
+Subject: [PATCH] drm/vc4: Allow interlaced HDMI modes from FKMS.
+
+Having checked the firmware handling for interlaced modes,
+it appears to be possible to support interlaced modes on
+HDMI without adverse side effects, so do so.
+
+https://github.com/raspberrypi/linux/issues/3694
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -936,6 +936,9 @@ static void vc4_crtc_mode_set_nofb(struc
+               break;
+       }
++      if (mode->flags & DRM_MODE_FLAG_INTERLACE)
++              mb.timings.flags |= TIMINGS_FLAGS_INTERLACE;
++
+       mb.timings.video_id_code = frame.avi.video_code;
+       if (!vc4_encoder->hdmi_monitor) {
+@@ -1632,7 +1635,7 @@ vc4_fkms_connector_init(struct drm_devic
+                                  DRM_MODE_CONNECTOR_HDMIA);
+               drm_connector_helper_add(connector,
+                                        &vc4_fkms_connector_helper_funcs);
+-              connector->interlace_allowed = 0;
++              connector->interlace_allowed = 1;
+       }
+       ret = drm_mode_create_tv_margin_properties(dev);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0843-serial-8250-bcm2835aux-defer-if-clock-is-zero.patch b/target/linux/bcm27xx/patches-5.4/950-0843-serial-8250-bcm2835aux-defer-if-clock-is-zero.patch
new file mode 100644 (file)
index 0000000..b421ba9
--- /dev/null
@@ -0,0 +1,28 @@
+From 80163961af8e31a2045271c5a12adaae620445e1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 2 Jul 2020 13:53:20 +0100
+Subject: [PATCH] serial: 8250: bcm2835aux - defer if clock is zero
+
+See: https://github.com/raspberrypi/linux/issues/3700
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/tty/serial/8250/8250_bcm2835aux.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
++++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
+@@ -92,6 +92,13 @@ static int bcm2835aux_serial_probe(struc
+        */
+       data->uart.port.uartclk = clk_get_rate(data->clk) * 2;
++      /* The clock is only queried at probe time, which means we get one shot
++       * at this. A zero clock is never going to work and is almost certainly
++       * due to a parent not being ready, so prefer to defer.
++       */
++      if (!data->uart.port.uartclk)
++          return -EPROBE_DEFER;
++
+       /* register the port */
+       ret = serial8250_register_8250_port(&data->uart);
+       if (ret < 0) {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0844-media-v4l-Add-14-bit-raw-bayer-pixel-formats.patch b/target/linux/bcm27xx/patches-5.4/950-0844-media-v4l-Add-14-bit-raw-bayer-pixel-formats.patch
new file mode 100644 (file)
index 0000000..1bb9a93
--- /dev/null
@@ -0,0 +1,151 @@
+From 59a535539277240c4bdbb9c21bc07c8b586b2c3a Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+Date: Mon, 24 Feb 2020 18:52:20 +0100
+Subject: [PATCH] media: v4l: Add 14-bit raw bayer pixel formats
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit d12127ed0e18192491c2508caae45bb19c2f8fdd upstream.
+
+The formats added by this patch are:
+
+       V4L2_PIX_FMT_SBGGR14
+       V4L2_PIX_FMT_SGBRG14
+       V4L2_PIX_FMT_SGRBG14
+       V4L2_PIX_FMT_SRGGB14
+
+Signed-off-by: Jouni Ukkonen <jouni.ukkonen@intel.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+[dg@emlix.com: rebased onto current media_tree]
+Signed-off-by: Daniel Glöckner <dg@emlix.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ Documentation/media/uapi/v4l/pixfmt-bayer.rst |  1 +
+ .../media/uapi/v4l/pixfmt-srggb14.rst         | 82 +++++++++++++++++++
+ drivers/media/v4l2-core/v4l2-ioctl.c          |  4 +
+ include/uapi/linux/videodev2.h                |  4 +
+ 4 files changed, 91 insertions(+)
+ create mode 100644 Documentation/media/uapi/v4l/pixfmt-srggb14.rst
+
+--- a/Documentation/media/uapi/v4l/pixfmt-bayer.rst
++++ b/Documentation/media/uapi/v4l/pixfmt-bayer.rst
+@@ -34,5 +34,6 @@ orders. See also `the Wikipedia article
+     pixfmt-srggb10-ipu3
+     pixfmt-srggb12
+     pixfmt-srggb12p
++    pixfmt-srggb14
+     pixfmt-srggb14p
+     pixfmt-srggb16
+--- /dev/null
++++ b/Documentation/media/uapi/v4l/pixfmt-srggb14.rst
+@@ -0,0 +1,82 @@
++.. Permission is granted to copy, distribute and/or modify this
++.. document under the terms of the GNU Free Documentation License,
++.. Version 1.1 or any later version published by the Free Software
++.. Foundation, with no Invariant Sections, no Front-Cover Texts
++.. and no Back-Cover Texts. A copy of the license is included at
++.. Documentation/media/uapi/fdl-appendix.rst.
++..
++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
++
++.. _V4L2-PIX-FMT-SRGGB14:
++.. _v4l2-pix-fmt-sbggr14:
++.. _v4l2-pix-fmt-sgbrg14:
++.. _v4l2-pix-fmt-sgrbg14:
++
++
++***************************************************************************************************************************
++V4L2_PIX_FMT_SRGGB14 ('RG14'), V4L2_PIX_FMT_SGRBG14 ('GR14'), V4L2_PIX_FMT_SGBRG14 ('GB14'), V4L2_PIX_FMT_SBGGR14 ('BG14'),
++***************************************************************************************************************************
++
++
++14-bit Bayer formats expanded to 16 bits
++
++
++Description
++===========
++
++These four pixel formats are raw sRGB / Bayer formats with 14 bits per
++colour. Each sample is stored in a 16-bit word, with two unused high
++bits filled with zeros. Each n-pixel row contains n/2 green samples
++and n/2 blue or red samples, with alternating red and blue rows. Bytes
++are stored in memory in little endian order. They are conventionally
++described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an
++example of a small V4L2_PIX_FMT_SBGGR14 image:
++
++**Byte Order.**
++Each cell is one byte, the two most significant bits in the high bytes are
++zero.
++
++
++
++.. flat-table::
++    :header-rows:  0
++    :stub-columns: 0
++    :widths:       2 1 1 1 1 1 1 1 1
++
++
++    * - start + 0:
++      - B\ :sub:`00low`
++      - B\ :sub:`00high`
++      - G\ :sub:`01low`
++      - G\ :sub:`01high`
++      - B\ :sub:`02low`
++      - B\ :sub:`02high`
++      - G\ :sub:`03low`
++      - G\ :sub:`03high`
++    * - start + 8:
++      - G\ :sub:`10low`
++      - G\ :sub:`10high`
++      - R\ :sub:`11low`
++      - R\ :sub:`11high`
++      - G\ :sub:`12low`
++      - G\ :sub:`12high`
++      - R\ :sub:`13low`
++      - R\ :sub:`13high`
++    * - start + 16:
++      - B\ :sub:`20low`
++      - B\ :sub:`20high`
++      - G\ :sub:`21low`
++      - G\ :sub:`21high`
++      - B\ :sub:`22low`
++      - B\ :sub:`22high`
++      - G\ :sub:`23low`
++      - G\ :sub:`23high`
++    * - start + 24:
++      - G\ :sub:`30low`
++      - G\ :sub:`30high`
++      - R\ :sub:`31low`
++      - R\ :sub:`31high`
++      - G\ :sub:`32low`
++      - G\ :sub:`32high`
++      - R\ :sub:`33low`
++      - R\ :sub:`33high`
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -1298,6 +1298,10 @@ static void v4l_fill_fmtdesc(struct v4l2
+       case V4L2_PIX_FMT_SGBRG12P:     descr = "12-bit Bayer GBGB/RGRG Packed"; break;
+       case V4L2_PIX_FMT_SGRBG12P:     descr = "12-bit Bayer GRGR/BGBG Packed"; break;
+       case V4L2_PIX_FMT_SRGGB12P:     descr = "12-bit Bayer RGRG/GBGB Packed"; break;
++      case V4L2_PIX_FMT_SBGGR14:      descr = "14-bit Bayer BGBG/GRGR"; break;
++      case V4L2_PIX_FMT_SGBRG14:      descr = "14-bit Bayer GBGB/RGRG"; break;
++      case V4L2_PIX_FMT_SGRBG14:      descr = "14-bit Bayer GRGR/BGBG"; break;
++      case V4L2_PIX_FMT_SRGGB14:      descr = "14-bit Bayer RGRG/GBGB"; break;
+       case V4L2_PIX_FMT_SBGGR14P:     descr = "14-bit Bayer BGBG/GRGR Packed"; break;
+       case V4L2_PIX_FMT_SGBRG14P:     descr = "14-bit Bayer GBGB/RGRG Packed"; break;
+       case V4L2_PIX_FMT_SGRBG14P:     descr = "14-bit Bayer GRGR/BGBG Packed"; break;
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -666,6 +666,10 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_SGBRG12P v4l2_fourcc('p', 'G', 'C', 'C')
+ #define V4L2_PIX_FMT_SGRBG12P v4l2_fourcc('p', 'g', 'C', 'C')
+ #define V4L2_PIX_FMT_SRGGB12P v4l2_fourcc('p', 'R', 'C', 'C')
++#define V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4') /* 14  BGBG.. GRGR.. */
++#define V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4') /* 14  GBGB.. RGRG.. */
++#define V4L2_PIX_FMT_SGRBG14 v4l2_fourcc('G', 'R', '1', '4') /* 14  GRGR.. BGBG.. */
++#define V4L2_PIX_FMT_SRGGB14 v4l2_fourcc('R', 'G', '1', '4') /* 14  RGRG.. GBGB.. */
+       /* 14bit raw bayer packed, 7 bytes for every 4 pixels */
+ #define V4L2_PIX_FMT_SBGGR14P v4l2_fourcc('p', 'B', 'E', 'E')
+ #define V4L2_PIX_FMT_SGBRG14P v4l2_fourcc('p', 'G', 'E', 'E')
diff --git a/target/linux/bcm27xx/patches-5.4/950-0845-media-v4l-Add-14-bit-raw-greyscale-pixel-format.patch b/target/linux/bcm27xx/patches-5.4/950-0845-media-v4l-Add-14-bit-raw-greyscale-pixel-format.patch
new file mode 100644 (file)
index 0000000..1910668
--- /dev/null
@@ -0,0 +1,131 @@
+From 363792f3fff5f4f79e2ac08ccfcc21c05216787a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= <dg@emlix.com>
+Date: Mon, 24 Feb 2020 18:52:21 +0100
+Subject: [PATCH] media: v4l: Add 14-bit raw greyscale pixel format
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit ae9753a04cfc8e41262605875e531b6ea5e3d0ac upstream.
+
+The new format is called V4L2_PIX_FMT_Y14. Like V4L2_PIX_FMT_Y10 and
+V4L2_PIX_FMT_Y12 it is stored in two bytes per pixel but has only two
+unused bits at the top.
+
+Signed-off-by: Daniel Glöckner <dg@emlix.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ Documentation/media/uapi/v4l/pixfmt-y14.rst  | 72 ++++++++++++++++++++
+ Documentation/media/uapi/v4l/yuv-formats.rst |  1 +
+ drivers/media/v4l2-core/v4l2-ioctl.c         |  1 +
+ include/uapi/linux/videodev2.h               |  1 +
+ 4 files changed, 75 insertions(+)
+ create mode 100644 Documentation/media/uapi/v4l/pixfmt-y14.rst
+
+--- /dev/null
++++ b/Documentation/media/uapi/v4l/pixfmt-y14.rst
+@@ -0,0 +1,72 @@
++.. Permission is granted to copy, distribute and/or modify this
++.. document under the terms of the GNU Free Documentation License,
++.. Version 1.1 or any later version published by the Free Software
++.. Foundation, with no Invariant Sections, no Front-Cover Texts
++.. and no Back-Cover Texts. A copy of the license is included at
++.. Documentation/media/uapi/fdl-appendix.rst.
++..
++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
++
++.. _V4L2-PIX-FMT-Y14:
++
++*************************
++V4L2_PIX_FMT_Y14 ('Y14 ')
++*************************
++
++
++Grey-scale image
++
++
++Description
++===========
++
++This is a grey-scale image with a depth of 14 bits per pixel. Pixels are
++stored in 16-bit words with unused high bits padded with 0. The least
++significant byte is stored at lower memory addresses (little-endian).
++
++**Byte Order.**
++Each cell is one byte.
++
++
++
++
++.. flat-table::
++    :header-rows:  0
++    :stub-columns: 0
++
++    * - start + 0:
++      - Y'\ :sub:`00low`
++      - Y'\ :sub:`00high`
++      - Y'\ :sub:`01low`
++      - Y'\ :sub:`01high`
++      - Y'\ :sub:`02low`
++      - Y'\ :sub:`02high`
++      - Y'\ :sub:`03low`
++      - Y'\ :sub:`03high`
++    * - start + 8:
++      - Y'\ :sub:`10low`
++      - Y'\ :sub:`10high`
++      - Y'\ :sub:`11low`
++      - Y'\ :sub:`11high`
++      - Y'\ :sub:`12low`
++      - Y'\ :sub:`12high`
++      - Y'\ :sub:`13low`
++      - Y'\ :sub:`13high`
++    * - start + 16:
++      - Y'\ :sub:`20low`
++      - Y'\ :sub:`20high`
++      - Y'\ :sub:`21low`
++      - Y'\ :sub:`21high`
++      - Y'\ :sub:`22low`
++      - Y'\ :sub:`22high`
++      - Y'\ :sub:`23low`
++      - Y'\ :sub:`23high`
++    * - start + 24:
++      - Y'\ :sub:`30low`
++      - Y'\ :sub:`30high`
++      - Y'\ :sub:`31low`
++      - Y'\ :sub:`31high`
++      - Y'\ :sub:`32low`
++      - Y'\ :sub:`32high`
++      - Y'\ :sub:`33low`
++      - Y'\ :sub:`33high`
+--- a/Documentation/media/uapi/v4l/yuv-formats.rst
++++ b/Documentation/media/uapi/v4l/yuv-formats.rst
+@@ -35,6 +35,7 @@ to brightness information.
+     pixfmt-grey
+     pixfmt-y10
+     pixfmt-y12
++    pixfmt-y14
+     pixfmt-y10b
+     pixfmt-y10p
+     pixfmt-y16
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -1212,6 +1212,7 @@ static void v4l_fill_fmtdesc(struct v4l2
+       case V4L2_PIX_FMT_Y6:           descr = "6-bit Greyscale"; break;
+       case V4L2_PIX_FMT_Y10:          descr = "10-bit Greyscale"; break;
+       case V4L2_PIX_FMT_Y12:          descr = "12-bit Greyscale"; break;
++      case V4L2_PIX_FMT_Y14:          descr = "14-bit Greyscale"; break;
+       case V4L2_PIX_FMT_Y16:          descr = "16-bit Greyscale"; break;
+       case V4L2_PIX_FMT_Y16_BE:       descr = "16-bit Greyscale BE"; break;
+       case V4L2_PIX_FMT_Y10BPACK:     descr = "10-bit Greyscale (Packed)"; break;
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -569,6 +569,7 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_Y6      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
+ #define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
+ #define V4L2_PIX_FMT_Y12     v4l2_fourcc('Y', '1', '2', ' ') /* 12  Greyscale     */
++#define V4L2_PIX_FMT_Y14     v4l2_fourcc('Y', '1', '4', ' ') /* 14  Greyscale     */
+ #define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
+ #define V4L2_PIX_FMT_Y16_BE  v4l2_fourcc_be('Y', '1', '6', ' ') /* 16  Greyscale BE  */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0846-media-v4l-Add-1X14-14-bit-greyscale-media-bus-code-d.patch b/target/linux/bcm27xx/patches-5.4/950-0846-media-v4l-Add-1X14-14-bit-greyscale-media-bus-code-d.patch
new file mode 100644 (file)
index 0000000..09c4330
--- /dev/null
@@ -0,0 +1,88 @@
+From efc06d6c82d5b6b3ee5dd2bfa7c010f737a0fa49 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= <dg@emlix.com>
+Date: Mon, 24 Feb 2020 18:52:22 +0100
+Subject: [PATCH] media: v4l: Add 1X14 14-bit greyscale media bus
+ code definition
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 573a750813459725c6f6fc4bc5779da1fe03238a upstream.
+
+The code is called MEDIA_BUS_FMT_Y14_1X14 and behaves just like
+MEDIA_BUS_FMT_Y12_1X12 with two more bits.
+
+Signed-off-by: Daniel Glöckner <dg@emlix.com>
+Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+---
+ .../media/uapi/v4l/subdev-formats.rst         | 37 +++++++++++++++++++
+ include/uapi/linux/media-bus-format.h         |  3 +-
+ 2 files changed, 39 insertions(+), 1 deletion(-)
+
+--- a/Documentation/media/uapi/v4l/subdev-formats.rst
++++ b/Documentation/media/uapi/v4l/subdev-formats.rst
+@@ -5792,6 +5792,43 @@ the following codes.
+       - u\ :sub:`2`
+       - u\ :sub:`1`
+       - u\ :sub:`0`
++    * .. _MEDIA-BUS-FMT-Y14-1X14:
++
++      - MEDIA_BUS_FMT_Y14_1X14
++      - 0x202d
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      -
++      - y\ :sub:`13`
++      - y\ :sub:`12`
++      - y\ :sub:`11`
++      - y\ :sub:`10`
++      - y\ :sub:`9`
++      - y\ :sub:`8`
++      - y\ :sub:`7`
++      - y\ :sub:`6`
++      - y\ :sub:`5`
++      - y\ :sub:`4`
++      - y\ :sub:`3`
++      - y\ :sub:`2`
++      - y\ :sub:`1`
++      - y\ :sub:`0`
+     * .. _MEDIA-BUS-FMT-UYVY8-1X16:
+       - MEDIA_BUS_FMT_UYVY8_1X16
+--- a/include/uapi/linux/media-bus-format.h
++++ b/include/uapi/linux/media-bus-format.h
+@@ -64,7 +64,7 @@
+ #define MEDIA_BUS_FMT_RGB121212_1X36          0x1019
+ #define MEDIA_BUS_FMT_RGB161616_1X48          0x101a
+-/* YUV (including grey) - next is     0x202d */
++/* YUV (including grey) - next is     0x202e */
+ #define MEDIA_BUS_FMT_Y8_1X8                  0x2001
+ #define MEDIA_BUS_FMT_UV8_1X8                 0x2015
+ #define MEDIA_BUS_FMT_UYVY8_1_5X8             0x2002
+@@ -86,6 +86,7 @@
+ #define MEDIA_BUS_FMT_VYUY12_2X12             0x201d
+ #define MEDIA_BUS_FMT_YUYV12_2X12             0x201e
+ #define MEDIA_BUS_FMT_YVYU12_2X12             0x201f
++#define MEDIA_BUS_FMT_Y14_1X14                        0x202d
+ #define MEDIA_BUS_FMT_UYVY8_1X16              0x200f
+ #define MEDIA_BUS_FMT_VYUY8_1X16              0x2010
+ #define MEDIA_BUS_FMT_YUYV8_1X16              0x2011
diff --git a/target/linux/bcm27xx/patches-5.4/950-0847-media-Add-a-pixel-format-for-MIPI-packed-12bit-luma-.patch b/target/linux/bcm27xx/patches-5.4/950-0847-media-Add-a-pixel-format-for-MIPI-packed-12bit-luma-.patch
new file mode 100644 (file)
index 0000000..b5d407b
--- /dev/null
@@ -0,0 +1,95 @@
+From 14ed8669ba80f2bb9a5f0d6be51052813d4a75e8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 7 May 2020 16:59:03 +0100
+Subject: [PATCH] media: Add a pixel format for MIPI packed 12bit
+ luma only.
+
+This is the format used by monochrome 12bit image sensors.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ Documentation/media/uapi/v4l/pixfmt-y12p.rst | 45 ++++++++++++++++++++
+ Documentation/media/uapi/v4l/yuv-formats.rst |  1 +
+ drivers/media/v4l2-core/v4l2-ioctl.c         |  1 +
+ include/uapi/linux/videodev2.h               |  1 +
+ 4 files changed, 48 insertions(+)
+ create mode 100644 Documentation/media/uapi/v4l/pixfmt-y12p.rst
+
+--- /dev/null
++++ b/Documentation/media/uapi/v4l/pixfmt-y12p.rst
+@@ -0,0 +1,45 @@
++.. Permission is granted to copy, distribute and/or modify this
++.. document under the terms of the GNU Free Documentation License,
++.. Version 1.1 or any later version published by the Free Software
++.. Foundation, with no Invariant Sections, no Front-Cover Texts
++.. and no Back-Cover Texts. A copy of the license is included at
++.. Documentation/media/uapi/fdl-appendix.rst.
++..
++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
++
++.. _V4L2-PIX-FMT-Y12P:
++
++******************************
++V4L2_PIX_FMT_Y12P ('Y12P')
++******************************
++
++Grey-scale image as a MIPI RAW12 packed array
++
++
++Description
++===========
++
++This is a packed grey-scale image format with a depth of 12 bits per
++pixel. Two consecutive pixels are packed into 3 bytes. The first 2 bytes
++contain the 8 high order bits of the pixels, and the 3rd byte contains the 4
++least significants bits of each pixel, in the same order.
++
++**Byte Order.**
++Each cell is one byte.
++
++.. tabularcolumns:: |p{2.2cm}|p{1.2cm}|p{1.2cm}|p{3.1cm}|
++
++
++.. flat-table::
++    :header-rows:  0
++    :stub-columns: 0
++    :widths:       2 1 1 1
++
++
++    -  -  start + 0:
++       -  Y'\ :sub:`00high`
++       -  Y'\ :sub:`01high`
++       -  Y'\ :sub:`01low`\ (bits 7--4)
++
++          Y'\ :sub:`00low`\ (bits 3--0)
++
+--- a/Documentation/media/uapi/v4l/yuv-formats.rst
++++ b/Documentation/media/uapi/v4l/yuv-formats.rst
+@@ -35,6 +35,7 @@ to brightness information.
+     pixfmt-grey
+     pixfmt-y10
+     pixfmt-y12
++    pixfmt-y12p
+     pixfmt-y14
+     pixfmt-y10b
+     pixfmt-y10p
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -1217,6 +1217,7 @@ static void v4l_fill_fmtdesc(struct v4l2
+       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;
++      case V4L2_PIX_FMT_Y12P:         descr = "12-bit Greyscale (MIPI Packed)"; break;
+       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;
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -576,6 +576,7 @@ struct v4l2_pix_format {
+ /* Grey bit-packed formats */
+ #define V4L2_PIX_FMT_Y10BPACK    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
+ #define V4L2_PIX_FMT_Y10P    v4l2_fourcc('Y', '1', '0', 'P') /* 10  Greyscale, MIPI RAW10 packed */
++#define V4L2_PIX_FMT_Y12P    v4l2_fourcc('Y', '1', '2', 'P') /* 12  Greyscale, MIPI RAW12 packed */
+ /* Palette formats */
+ #define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0848-media-Add-a-pixel-format-for-MIPI-packed-14bit-luma-.patch b/target/linux/bcm27xx/patches-5.4/950-0848-media-Add-a-pixel-format-for-MIPI-packed-14bit-luma-.patch
new file mode 100644 (file)
index 0000000..f8b255f
--- /dev/null
@@ -0,0 +1,104 @@
+From 8c51a9a891458e5d66cfedea84b1a38ceb01b7ae Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 17:51:03 +0100
+Subject: [PATCH] media: Add a pixel format for MIPI packed 14bit
+ luma only.
+
+This is the format used by monochrome 14bit image sensors.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ Documentation/media/uapi/v4l/pixfmt-y14p.rst | 54 ++++++++++++++++++++
+ Documentation/media/uapi/v4l/yuv-formats.rst |  1 +
+ drivers/media/v4l2-core/v4l2-ioctl.c         |  1 +
+ include/uapi/linux/videodev2.h               |  1 +
+ 4 files changed, 57 insertions(+)
+ create mode 100644 Documentation/media/uapi/v4l/pixfmt-y14p.rst
+
+--- /dev/null
++++ b/Documentation/media/uapi/v4l/pixfmt-y14p.rst
+@@ -0,0 +1,54 @@
++.. Permission is granted to copy, distribute and/or modify this
++.. document under the terms of the GNU Free Documentation License,
++.. Version 1.1 or any later version published by the Free Software
++.. Foundation, with no Invariant Sections, no Front-Cover Texts
++.. and no Back-Cover Texts. A copy of the license is included at
++.. Documentation/media/uapi/fdl-appendix.rst.
++..
++.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections
++
++.. _V4L2-PIX-FMT-Y14P:
++
++**************************
++V4L2_PIX_FMT_Y14P ('Y14P')
++**************************
++
++Grey-scale image as a MIPI RAW14 packed array
++
++
++Description
++===========
++
++This is a packed grey-scale image format with a depth of 14 bits per
++pixel. Every four consecutive samples are packed into seven bytes. Each
++of the first four bytes contain the eight high order bits of the pixels,
++and the three following bytes contains the six least significants bits of
++each pixel, in the same order.
++
++**Byte Order.**
++Each cell is one byte.
++
++.. tabularcolumns:: |p{1.8cm}|p{1.0cm}|p{1.0cm}|p{1.0cm}|p{1.1cm}|p{3.3cm}|p{3.3cm}|p{3.3cm}|
++
++.. flat-table::
++    :header-rows:  0
++    :stub-columns: 0
++    :widths:       2 1 1 1 1 3 3 3
++
++
++    -  -  start + 0:
++       -  Y'\ :sub:`00high`
++       -  Y'\ :sub:`01high`
++       -  Y'\ :sub:`02high`
++       -  Y'\ :sub:`03high`
++       -  Y'\ :sub:`01low bits 1--0`\ (bits 7--6)
++
++        Y'\ :sub:`00low bits 5--0`\ (bits 5--0)
++
++       -  Y'\ :sub:`02low bits 3--0`\ (bits 7--4)
++
++        Y'\ :sub:`01low bits 5--2`\ (bits 3--0)
++
++       -  Y'\ :sub:`03low bits 5--0`\ (bits 7--2)
++
++        Y'\ :sub:`02low bits 5--4`\ (bits 1--0)
+--- a/Documentation/media/uapi/v4l/yuv-formats.rst
++++ b/Documentation/media/uapi/v4l/yuv-formats.rst
+@@ -37,6 +37,7 @@ to brightness information.
+     pixfmt-y12
+     pixfmt-y12p
+     pixfmt-y14
++    pixfmt-y14p
+     pixfmt-y10b
+     pixfmt-y10p
+     pixfmt-y16
+--- a/drivers/media/v4l2-core/v4l2-ioctl.c
++++ b/drivers/media/v4l2-core/v4l2-ioctl.c
+@@ -1218,6 +1218,7 @@ static void v4l_fill_fmtdesc(struct v4l2
+       case V4L2_PIX_FMT_Y10BPACK:     descr = "10-bit Greyscale (Packed)"; break;
+       case V4L2_PIX_FMT_Y10P:         descr = "10-bit Greyscale (MIPI Packed)"; break;
+       case V4L2_PIX_FMT_Y12P:         descr = "12-bit Greyscale (MIPI Packed)"; break;
++      case V4L2_PIX_FMT_Y14P:         descr = "14-bit Greyscale (MIPI Packed)"; break;
+       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;
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -577,6 +577,7 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_Y10BPACK    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
+ #define V4L2_PIX_FMT_Y10P    v4l2_fourcc('Y', '1', '0', 'P') /* 10  Greyscale, MIPI RAW10 packed */
+ #define V4L2_PIX_FMT_Y12P    v4l2_fourcc('Y', '1', '2', 'P') /* 12  Greyscale, MIPI RAW12 packed */
++#define V4L2_PIX_FMT_Y14P    v4l2_fourcc('Y', '1', '4', 'P') /* 14  Greyscale, MIPI RAW12 packed */
+ /* Palette formats */
+ #define V4L2_PIX_FMT_PAL8    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0849-staging-vc04_services-isp-Add-support-for-14bit-Baye.patch b/target/linux/bcm27xx/patches-5.4/950-0849-staging-vc04_services-isp-Add-support-for-14bit-Baye.patch
new file mode 100644 (file)
index 0000000..837b6b5
--- /dev/null
@@ -0,0 +1,75 @@
+From ac6ebed4a0e06b4102831976e826a5986732ed33 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 6 May 2020 18:09:04 +0100
+Subject: [PATCH] staging: vc04_services: isp: Add support for 14bit
+ Bayer
+
+The only thing missing was a set of defines, therefore add them in.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-isp/bcm2835_isp_fmts.h            | 37 +++++++++++++++++++
+ .../vc04_services/vchiq-mmal/mmal-encodings.h |  6 +++
+ 2 files changed, 43 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_fmts.h
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_fmts.h
+@@ -254,6 +254,43 @@ static const struct bcm2835_isp_fmt supp
+               .colorspace         = V4L2_COLORSPACE_RAW,
+               .step_size          = 2,
+       }, {
++              /* 14 bit */
++              .fourcc             = V4L2_PIX_FMT_SRGGB14P,
++              .depth              = 14,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_BAYER_SRGGB14P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              .fourcc             = V4L2_PIX_FMT_SBGGR14P,
++              .depth              = 14,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_BAYER_SBGGR14P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              .fourcc             = V4L2_PIX_FMT_SGRBG14P,
++              .depth              = 14,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_BAYER_SGRBG14P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              .fourcc             = V4L2_PIX_FMT_SGBRG14P,
++              .depth              = 14,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_BAYER_SGBRG14P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
+               /* 16 bit */
+               .fourcc             = V4L2_PIX_FMT_SRGGB16,
+               .depth              = 16,
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -90,6 +90,12 @@
+ #define MMAL_ENCODING_BAYER_SGBRG12P   MMAL_FOURCC('p', 'G', '1', '2')
+ #define MMAL_ENCODING_BAYER_SRGGB12P   MMAL_FOURCC('p', 'R', '1', '2')
++//14 bit per pixel Bayer formats.
++#define MMAL_ENCODING_BAYER_SBGGR14P   MMAL_FOURCC('p', 'B', 'E', 'E')
++#define MMAL_ENCODING_BAYER_SGBRG14P   MMAL_FOURCC('p', 'G', 'E', 'E')
++#define MMAL_ENCODING_BAYER_SGRBG14P   MMAL_FOURCC('p', 'g', 'E', 'E')
++#define MMAL_ENCODING_BAYER_SRGGB14P   MMAL_FOURCC('p', 'R', 'E', 'E')
++
+ /* 16 bit per pixel Bayer formats. */
+ #define MMAL_ENCODING_BAYER_SBGGR16    MMAL_FOURCC('B', 'G', '1', '6')
+ #define MMAL_ENCODING_BAYER_SGBRG16    MMAL_FOURCC('G', 'B', '1', '6')
diff --git a/target/linux/bcm27xx/patches-5.4/950-0850-staging-vc04_services-isp-Add-monochrome-image-forma.patch b/target/linux/bcm27xx/patches-5.4/950-0850-staging-vc04_services-isp-Add-monochrome-image-forma.patch
new file mode 100644 (file)
index 0000000..849417f
--- /dev/null
@@ -0,0 +1,92 @@
+From ef305037fd7423386d3a59b640114bdff67d824f Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 6 May 2020 18:11:14 +0100
+Subject: [PATCH] staging: vc04_services: isp: Add monochrome image
+ formats
+
+Adds support for monochrome image formats in the various
+MIPI packings.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-isp/bcm2835_isp_fmts.h            | 52 ++++++++++++++++++-
+ .../vc04_services/vchiq-mmal/mmal-encodings.h |  7 +++
+ 2 files changed, 58 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_fmts.h
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_fmts.h
+@@ -328,7 +328,57 @@ static const struct bcm2835_isp_fmt supp
+               .colorspace         = V4L2_COLORSPACE_RAW,
+               .step_size          = 2,
+       }, {
+-              /* ISP statistics format */
++              /* Monochrome MIPI formats */
++              /* 8 bit */
++              .fourcc             = V4L2_PIX_FMT_GREY,
++              .depth              = 8,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_GREY,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              /* 10 bit */
++              .fourcc             = V4L2_PIX_FMT_Y10P,
++              .depth              = 10,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_Y10P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              /* 12 bit */
++              .fourcc             = V4L2_PIX_FMT_Y12P,
++              .depth              = 12,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_Y12P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              /* 14 bit */
++              .fourcc             = V4L2_PIX_FMT_Y14P,
++              .depth              = 14,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_Y14P,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
++              /* 16 bit */
++              .fourcc             = V4L2_PIX_FMT_Y16,
++              .depth              = 16,
++              .bytesperline_align = 32,
++              .flags              = 0,
++              .mmal_fmt           = MMAL_ENCODING_Y16,
++              .size_multiplier_x2 = 2,
++              .colorspace         = V4L2_COLORSPACE_RAW,
++              .step_size          = 2,
++      }, {
+               .fourcc             = V4L2_META_FMT_BCM2835_ISP_STATS,
+               .mmal_fmt           = MMAL_ENCODING_BRCM_STATS,
+               /* The rest are not valid fields for stats. */
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -102,6 +102,13 @@
+ #define MMAL_ENCODING_BAYER_SGRBG16    MMAL_FOURCC('G', 'R', '1', '6')
+ #define MMAL_ENCODING_BAYER_SRGGB16    MMAL_FOURCC('R', 'G', '1', '6')
++/* MIPI packed monochrome images */
++#define MMAL_ENCODING_GREY    MMAL_FOURCC('G', 'R', 'E', 'Y')
++#define MMAL_ENCODING_Y10P    MMAL_FOURCC('Y', '1', '0', 'P')
++#define MMAL_ENCODING_Y12P    MMAL_FOURCC('Y', '1', '2', 'P')
++#define MMAL_ENCODING_Y14P    MMAL_FOURCC('Y', '1', '4', 'P')
++#define MMAL_ENCODING_Y16     MMAL_FOURCC('Y', '1', '6', ' ')
++
+ /** An EGL image handle
+  */
+ #define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
diff --git a/target/linux/bcm27xx/patches-5.4/950-0851-staging-vc04_services-isp-Increase-the-number-of-sup.patch b/target/linux/bcm27xx/patches-5.4/950-0851-staging-vc04_services-isp-Increase-the-number-of-sup.patch
new file mode 100644 (file)
index 0000000..ebf16db
--- /dev/null
@@ -0,0 +1,29 @@
+From 9b0b99ee3711846203d6f2500925e8b463fbeb8e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 6 May 2020 18:24:34 +0100
+Subject: [PATCH] staging: vc04_services: isp: Increase the number of
+ supported formats expected
+
+The ISP now supports 47 different input formats, therefore increase the
+array size for the number expected.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -1134,10 +1134,10 @@ static const struct v4l2_ioctl_ops bcm28
+  * Size of the array to provide to the VPU when asking for the list of supported
+  * formats.
+  *
+- * The ISP component currently advertises 33 input formats, so add a small
++ * The ISP component currently advertises 44 input formats, so add a small
+  * overhead on that.
+  */
+-#define MAX_SUPPORTED_ENCODINGS 40
++#define MAX_SUPPORTED_ENCODINGS 50
+ /* Populate node->supported_fmts with the formats supported by those ports. */
+ static int bcm2835_isp_get_supported_fmts(struct bcm2835_isp_node *node)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0852-staging-vc04_services-codec-Increase-the-number-of-s.patch b/target/linux/bcm27xx/patches-5.4/950-0852-staging-vc04_services-codec-Increase-the-number-of-s.patch
new file mode 100644 (file)
index 0000000..c4e20c6
--- /dev/null
@@ -0,0 +1,29 @@
+From 8827ec069302241c3a22371887d3980b9f855bba Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 17:40:56 +0100
+Subject: [PATCH] staging: vc04_services: codec: Increase the number
+ of supported formats expected
+
+The ISP now supports 47 different input formats, therefore increase the
+array size for the number expected.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c  | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2569,10 +2569,10 @@ static const struct v4l2_m2m_ops m2m_ops
+ /* Size of the array to provide to the VPU when asking for the list of supported
+  * formats.
+- * The ISP component currently advertises 33 input formats, so add a small
++ * The ISP component currently advertises 44 input formats, so add a small
+  * overhead on that.
+  */
+-#define MAX_SUPPORTED_ENCODINGS 40
++#define MAX_SUPPORTED_ENCODINGS 50
+ /* Populate dev->supported_fmts with the formats supported by those ports. */
+ static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0853-staging-vc04_services-codec-Add-support-for-mono-for.patch b/target/linux/bcm27xx/patches-5.4/950-0853-staging-vc04_services-codec-Add-support-for-mono-for.patch
new file mode 100644 (file)
index 0000000..620ad14
--- /dev/null
@@ -0,0 +1,64 @@
+From 6e6861281012b9ac99b85b9e2703cad35d91c279 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 1 Jul 2020 10:38:12 +0100
+Subject: [PATCH] staging: vc04_services: codec: Add support for mono
+ formats
+
+The firmware ISP component now allows for processing of mono
+images, so add those formats for use by the simple ISP device.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 41 +++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -344,6 +344,47 @@ static const struct bcm2835_codec_fmt su
+               .size_multiplier_x2     = 2,
+               .is_bayer               = true,
+       }, {
++              /* Monochrome MIPI formats */
++              /* 8 bit */
++              .fourcc                 = V4L2_PIX_FMT_GREY,
++              .depth                  = 8,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_GREY,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 10 bit */
++              .fourcc                 = V4L2_PIX_FMT_Y10P,
++              .depth                  = 10,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_Y10P,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 12 bit */
++              .fourcc                 = V4L2_PIX_FMT_Y12P,
++              .depth                  = 12,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_Y12P,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 14 bit */
++              .fourcc                 = V4L2_PIX_FMT_Y14P,
++              .depth                  = 14,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_Y14P,
++              .size_multiplier_x2     = 2,
++      }, {
++              /* 16 bit */
++              .fourcc                 = V4L2_PIX_FMT_Y16,
++              .depth                  = 16,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_Y16,
++              .size_multiplier_x2     = 2,
++      }, {
+               /* Compressed formats */
+               .fourcc                 = V4L2_PIX_FMT_H264,
+               .depth                  = 0,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0854-staging-vc04_services-codec-Add-support-for-14bit-Ba.patch b/target/linux/bcm27xx/patches-5.4/950-0854-staging-vc04_services-codec-Add-support-for-14bit-Ba.patch
new file mode 100644 (file)
index 0000000..e261f62
--- /dev/null
@@ -0,0 +1,57 @@
+From 34963c9fb717bc47131b662c34a472c4f717f7fe Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 1 Jul 2020 10:50:12 +0100
+Subject: [PATCH] staging: vc04_services: codec: Add support for
+ 14bit Bayer formats
+
+Now that the 14bit Bayer formats have been defined within
+V4L2, add them to the lookup table of V4L2/MMAL formats.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 34 +++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -311,6 +311,40 @@ static const struct bcm2835_codec_fmt su
+               .size_multiplier_x2     = 2,
+               .is_bayer               = true,
+       }, {
++              /* 14 bit */
++              .fourcc                 = V4L2_PIX_FMT_SRGGB14P,
++              .depth                  = 14,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB14P,
++              .size_multiplier_x2     = 2,
++              .is_bayer               = true,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SBGGR14P,
++              .depth                  = 14,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR14P,
++              .size_multiplier_x2     = 2,
++              .is_bayer               = true,
++
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGRBG14P,
++              .depth                  = 14,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG14P,
++              .size_multiplier_x2     = 2,
++              .is_bayer               = true,
++      }, {
++              .fourcc                 = V4L2_PIX_FMT_SGBRG14P,
++              .depth                  = 14,
++              .bytesperline_align     = 32,
++              .flags                  = 0,
++              .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG14P,
++              .size_multiplier_x2     = 2,
++              .is_bayer               = true,
++      }, {
+               /* 16 bit */
+               .fourcc                 = V4L2_PIX_FMT_SRGGB16,
+               .depth                  = 16,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0855-media-bcm2835-unicam-Add-support-for-12bit-mono-pack.patch b/target/linux/bcm27xx/patches-5.4/950-0855-media-bcm2835-unicam-Add-support-for-12bit-mono-pack.patch
new file mode 100644 (file)
index 0000000..fdef58c
--- /dev/null
@@ -0,0 +1,25 @@
+From 511c9a4b7c3d2e40eee68dad4d4c02ca42678204 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 17:53:32 +0100
+Subject: [PATCH] media: bcm2835-unicam: Add support for 12bit mono
+ packed format
+
+Now that V4L2_PIX_FMT_Y12P is defined, allow passing raw 12bit
+mono packed data through the peripheral.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -336,7 +336,7 @@ static const struct unicam_fmt formats[]
+               .depth          = 10,
+               .csi_dt         = 0x2b,
+       }, {
+-              /* NB There is no packed V4L2 fourcc for this format. */
++              .fourcc         = V4L2_PIX_FMT_Y12P,
+               .repacked_fourcc = V4L2_PIX_FMT_Y12,
+               .code           = MEDIA_BUS_FMT_Y12_1X12,
+               .depth          = 12,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0856-media-bcm2835-unicam-Add-support-for-14bit-mono-sour.patch b/target/linux/bcm27xx/patches-5.4/950-0856-media-bcm2835-unicam-Add-support-for-14bit-mono-sour.patch
new file mode 100644 (file)
index 0000000..a65945c
--- /dev/null
@@ -0,0 +1,29 @@
+From 668ed11b1e8fbbe7ad9a63abbfece67d44b0aa85 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 25 Jun 2020 18:03:47 +0100
+Subject: [PATCH] media: bcm2835-unicam: Add support for 14bit mono
+ sources
+
+Now that V4L2_PIX_FMT_Y14 and V4L2_PIX_FMT_Y14P are defined,
+allow passing 14bit mono data through the peripheral.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -341,6 +341,12 @@ static const struct unicam_fmt formats[]
+               .code           = MEDIA_BUS_FMT_Y12_1X12,
+               .depth          = 12,
+               .csi_dt         = 0x2c,
++      }, {
++              .fourcc         = V4L2_PIX_FMT_Y14P,
++              .repacked_fourcc = V4L2_PIX_FMT_Y14,
++              .code           = MEDIA_BUS_FMT_Y14_1X14,
++              .depth          = 14,
++              .csi_dt         = 0x2d,
+       },
+       /* Embedded data format */
+       {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0857-media-bcm2835-unicam-Add-support-for-unpacked-14bit-.patch b/target/linux/bcm27xx/patches-5.4/950-0857-media-bcm2835-unicam-Add-support-for-unpacked-14bit-.patch
new file mode 100644 (file)
index 0000000..b52a59a
--- /dev/null
@@ -0,0 +1,42 @@
+From 9c0121e45af13c0b0850601ee4d88029c548b240 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 1 Jul 2020 10:57:57 +0100
+Subject: [PATCH] media: bcm2835-unicam: Add support for unpacked
+ 14bit Bayer formats
+
+Now that the 14bit non-packed Bayer formats are defined, add them
+into the supported formats lookup table.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -299,21 +299,25 @@ static const struct unicam_fmt formats[]
+               .csi_dt         = 0x2c,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SBGGR14P,
++              .repacked_fourcc = V4L2_PIX_FMT_SBGGR14,
+               .code           = MEDIA_BUS_FMT_SBGGR14_1X14,
+               .depth          = 14,
+               .csi_dt         = 0x2d,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SGBRG14P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGBRG14,
+               .code           = MEDIA_BUS_FMT_SGBRG14_1X14,
+               .depth          = 14,
+               .csi_dt         = 0x2d,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SGRBG14P,
++              .repacked_fourcc = V4L2_PIX_FMT_SGRBG14,
+               .code           = MEDIA_BUS_FMT_SGRBG14_1X14,
+               .depth          = 14,
+               .csi_dt         = 0x2d,
+       }, {
+               .fourcc         = V4L2_PIX_FMT_SRGGB14P,
++              .repacked_fourcc = V4L2_PIX_FMT_SRGGB14,
+               .code           = MEDIA_BUS_FMT_SRGGB14_1X14,
+               .depth          = 14,
+               .csi_dt         = 0x2d,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0858-overlays-Fix-miniuart-bt-krnbt-parameter.patch b/target/linux/bcm27xx/patches-5.4/950-0858-overlays-Fix-miniuart-bt-krnbt-parameter.patch
new file mode 100644 (file)
index 0000000..f7edf8a
--- /dev/null
@@ -0,0 +1,32 @@
+From 2d54451c77c85e153046baebdfedeabc224a59d7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 2 Jul 2020 15:21:05 +0100
+Subject: [PATCH] overlays: Fix miniuart-bt "krnbt" parameter
+
+Although superficially appealing, an overlay parameter that targets a
+label in the base DTB is not currently supported. Instead it is
+necessary to create a fragment targeting the label which is patched
+by the parameter.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
++++ b/arch/arm/boot/dts/overlays/miniuart-bt-overlay.dts
+@@ -81,7 +81,13 @@
+               };
+       };
++      fragment@7 {
++              target = <&minibt>;
++              minibt_frag: __overlay__ {
++              };
++      };
++
+       __overrides__ {
+-              krnbt = <&minibt>,"status";
++              krnbt = <&minibt_frag>,"status";
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0859-drm-vc4-Make-FKMS-max-refresh-rate-a-module-paramete.patch b/target/linux/bcm27xx/patches-5.4/950-0859-drm-vc4-Make-FKMS-max-refresh-rate-a-module-paramete.patch
new file mode 100644 (file)
index 0000000..bf27d7a
--- /dev/null
@@ -0,0 +1,55 @@
+From ff882e312a746a4a794a089e912e5e56baa8b5b4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 3 Jul 2020 14:11:55 +0100
+Subject: [PATCH] drm/vc4: Make FKMS max refresh rate a module
+ parameter
+
+Some people want to use the high refresh rate modes for 1080p100
+and 1080p120, but they're currently filtered out as generally
+they don't add anything.
+
+Make the filter threshold a module parameter so that it can be
+adjusted.
+
+https://github.com/raspberrypi/linux/issues/3677
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -14,6 +14,8 @@
+  * Pi's firmware display stack.
+  */
++#include <linux/module.h>
++
+ #include "drm/drm_atomic_helper.h"
+ #include "drm/drm_gem_framebuffer_helper.h"
+ #include "drm/drm_plane_helper.h"
+@@ -32,6 +34,10 @@
+ #include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
++int fkms_max_refresh_rate = 85;
++module_param(fkms_max_refresh_rate, int, 0644);
++MODULE_PARM_DESC(fkms_max_refresh_rate, "Max supported refresh rate");
++
+ struct get_display_cfg {
+       u32  max_pixel_clock[2];  //Max pixel clock for each display
+ };
+@@ -1069,8 +1075,10 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+               return MODE_NO_DBLESCAN;
+       }
+-      /* Disable refresh rates > 85Hz as limited gain from them */
+-      if (drm_mode_vrefresh(mode) > 85)
++      /* Disable refresh rates > defined threshold (default 85Hz) as limited
++       * gain from them
++       */
++      if (drm_mode_vrefresh(mode) > fkms_max_refresh_rate)
+               return MODE_BAD_VVALUE;
+       /* Limit the pixel clock based on the HDMI clock limits from the
diff --git a/target/linux/bcm27xx/patches-5.4/950-0860-drm-vc4-FKMS-Block-modes-with-odd-horizontal-timing-.patch b/target/linux/bcm27xx/patches-5.4/950-0860-drm-vc4-FKMS-Block-modes-with-odd-horizontal-timing-.patch
new file mode 100644 (file)
index 0000000..4bddd13
--- /dev/null
@@ -0,0 +1,74 @@
+From aa791f2cb6777e8ca99102009b631afdeea1c59d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 3 Jul 2020 16:06:55 +0100
+Subject: [PATCH] drm/vc4: FKMS Block modes with odd horizontal
+ timing values on Pi4
+
+Pi4 HDMI pipeline is 2 pixels/clock and can not produce timings
+that have odd values for active pixels, front porch, sync width,
+or back porch.
+Detect these modes and block them within fkms.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -44,6 +44,7 @@ struct get_display_cfg {
+ struct vc4_fkms {
+       struct get_display_cfg cfg;
++      bool bcm2711;
+ };
+ #define PLANES_PER_CRTC               3
+@@ -1097,6 +1098,17 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+               break;
+       }
++      /* Pi4 can't generate odd horizontal timings on HDMI, so reject modes
++       * that would set them.
++       */
++      if (fkms->bcm2711 &&
++          (vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) &&
++          ((mode->hdisplay |                          /* active */
++            (mode->hsync_start - mode->hdisplay) |    /* front porch */
++            (mode->hsync_end - mode->hsync_start) |   /* sync pulse */
++            (mode->htotal - mode->hsync_end)) & 1))   /* back porch */
++              return MODE_H_ILLEGAL;
++
+       return MODE_OK;
+ }
+@@ -1282,6 +1294,8 @@ static const struct drm_crtc_helper_func
+ static const struct of_device_id vc4_firmware_kms_dt_match[] = {
+       { .compatible = "raspberrypi,rpi-firmware-kms" },
++      { .compatible = "raspberrypi,rpi-firmware-kms-2711",
++        .data = (void *)1 },
+       {}
+ };
+@@ -1815,6 +1829,7 @@ static int vc4_fkms_bind(struct device *
+       struct drm_device *drm = dev_get_drvdata(master);
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
+       struct device_node *firmware_node;
++      const struct of_device_id *match;
+       struct vc4_crtc **crtc_list;
+       u32 num_displays, display_num;
+       struct vc4_fkms *fkms;
+@@ -1827,6 +1842,12 @@ static int vc4_fkms_bind(struct device *
+       if (!fkms)
+               return -ENOMEM;
++      match = of_match_device(vc4_firmware_kms_dt_match, dev);
++      if (!match)
++              return -ENODEV;
++      if (match->data)
++              fkms->bcm2711 = true;
++
+       /* firmware kms doesn't have precise a scanoutpos implementation, so
+        * we can't do the precise vblank timestamp mode.
+        */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0861-dt-Use-rpi-firmware-kms-2711-on-2711-platforms.patch b/target/linux/bcm27xx/patches-5.4/950-0861-dt-Use-rpi-firmware-kms-2711-on-2711-platforms.patch
new file mode 100644 (file)
index 0000000..d1805a6
--- /dev/null
@@ -0,0 +1,37 @@
+From 603b5b55d5f52869263647c44fe682d105f8ee46 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 3 Jul 2020 16:05:37 +0100
+Subject: [PATCH] dt: Use rpi-firmware-kms-2711 on 2711 platforms
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 4 ++++
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -443,6 +443,10 @@
+       };
+ };
++&firmwarekms {
++      compatible = "raspberrypi,rpi-firmware-kms-2711";
++};
++
+ // =============================================
+ // Board specific stuff here
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -461,6 +461,10 @@
+       };
+ };
++&firmwarekms {
++      compatible = "raspberrypi,rpi-firmware-kms-2711";
++};
++
+ // =============================================
+ // Board specific stuff here
diff --git a/target/linux/bcm27xx/patches-5.4/950-0862-drm-vc4-FKMS-Put-includes-in-alphabetical-order-and-.patch b/target/linux/bcm27xx/patches-5.4/950-0862-drm-vc4-FKMS-Put-includes-in-alphabetical-order-and-.patch
new file mode 100644 (file)
index 0000000..4adbe8a
--- /dev/null
@@ -0,0 +1,57 @@
+From 0a5e493ea20d9d24d0808d8a4e05a97deb19b423 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 3 Jul 2020 16:13:33 +0100
+Subject: [PATCH] drm/vc4: FKMS: Put includes in alphabetical order,
+ and use <> instead of ""
+
+Reorder the includes, and use the system include paths rather than
+local ones
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 29 +++++++++++++-------------
+ 1 file changed, 15 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -14,25 +14,26 @@
+  * Pi's firmware display stack.
+  */
++#include <drm/drm_atomic_helper.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_drv.h>
++#include <drm/drm_fb_cma_helper.h>
++#include <drm/drm_fourcc.h>
++#include <drm/drm_gem_framebuffer_helper.h>
++#include <drm/drm_plane_helper.h>
++#include <drm/drm_probe_helper.h>
++#include <drm/drm_vblank.h>
++
++#include <linux/component.h>
++#include <linux/clk.h>
++#include <linux/debugfs.h>
+ #include <linux/module.h>
+-#include "drm/drm_atomic_helper.h"
+-#include "drm/drm_gem_framebuffer_helper.h"
+-#include "drm/drm_plane_helper.h"
+-#include "drm/drm_crtc_helper.h"
+-#include "drm/drm_fourcc.h"
+-#include "drm/drm_probe_helper.h"
+-#include "drm/drm_drv.h"
+-#include "drm/drm_vblank.h"
+-#include "linux/clk.h"
+-#include "linux/debugfs.h"
+-#include "drm/drm_fb_cma_helper.h"
+-#include "linux/component.h"
+-#include "linux/of_device.h"
++#include <soc/bcm2835/raspberrypi-firmware.h>
++
+ #include "vc4_drv.h"
+ #include "vc4_regs.h"
+ #include "vc_image_types.h"
+-#include <soc/bcm2835/raspberrypi-firmware.h>
+ int fkms_max_refresh_rate = 85;
+ module_param(fkms_max_refresh_rate, int, 0644);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0863-irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch b/target/linux/bcm27xx/patches-5.4/950-0863-irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch
new file mode 100644 (file)
index 0000000..f27d448
--- /dev/null
@@ -0,0 +1,105 @@
+From 4ae861da5eaf53e5b4303f080bff0e34e22da0d9 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Tue, 4 Feb 2020 15:50:41 +0100
+Subject: [PATCH] irqchip/bcm2835: Quiesce IRQs left enabled by
+ bootloader
+
+[ Upstream commit bd59b343a9c902c522f006e6d71080f4893bbf42 ]
+
+Per the spec, the BCM2835's IRQs are all disabled when coming out of
+power-on reset.  Its IRQ driver assumes that's still the case when the
+kernel boots and does not perform any initialization of the registers.
+However the Raspberry Pi Foundation's bootloader leaves the USB
+interrupt enabled when handing over control to the kernel.
+
+Quiesce IRQs and the FIQ if they were left enabled and log a message to
+let users know that they should update the bootloader once a fixed
+version is released.
+
+If the USB interrupt is not quiesced and the USB driver later on claims
+the FIQ (as it does on the Raspberry Pi Foundation's downstream kernel),
+interrupt latency for all other peripherals increases and occasional
+lockups occur.  That's because both the FIQ and the normal USB interrupt
+fire simultaneously:
+
+On a multicore Raspberry Pi, if normal interrupts are routed to CPU 0
+and the FIQ to CPU 1 (hardcoded in the Foundation's kernel), then a USB
+interrupt causes CPU 0 to spin in bcm2836_chained_handle_irq() until the
+FIQ on CPU 1 has cleared it.  Other peripherals' interrupts are starved
+as long.  I've seen CPU 0 blocked for up to 2.9 msec.  eMMC throughput
+on a Compute Module 3 irregularly dips to 23.0 MB/s without this commit
+but remains relatively constant at 23.5 MB/s with this commit.
+
+The lockups occur when CPU 0 receives a USB interrupt while holding a
+lock which CPU 1 is trying to acquire while the FIQ is temporarily
+disabled on CPU 1.  At best users get RCU CPU stall warnings, but most
+of the time the system just freezes.
+
+Fixes: 89214f009c1d ("ARM: bcm2835: add interrupt controller driver")
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Link: https://lore.kernel.org/r/f97868ba4e9b86ddad71f44ec9d8b3b7d8daa1ea.1582618537.git.lukas@wunner.de
+---
+ drivers/irqchip/irq-bcm2835.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+--- a/drivers/irqchip/irq-bcm2835.c
++++ b/drivers/irqchip/irq-bcm2835.c
+@@ -67,8 +67,7 @@
+ #define ARM_LOCAL_GPU_INT_ROUTING 0x0c
+ #define REG_FIQ_CONTROL               0x0c
+-#define REG_FIQ_ENABLE                0x80
+-#define REG_FIQ_DISABLE               0
++#define FIQ_CONTROL_ENABLE    BIT(7)
+ #define NR_BANKS              3
+ #define IRQS_PER_BANK         32
+@@ -116,7 +115,7 @@ static inline unsigned int hwirq_to_fiq(
+ static void armctrl_mask_irq(struct irq_data *d)
+ {
+       if (d->hwirq >= NUMBER_IRQS)
+-              writel_relaxed(REG_FIQ_DISABLE, intc.base + REG_FIQ_CONTROL);
++              writel_relaxed(0, intc.base + REG_FIQ_CONTROL);
+       else
+               writel_relaxed(HWIRQ_BIT(d->hwirq),
+                              intc.disable[HWIRQ_BANK(d->hwirq)]);
+@@ -143,7 +142,7 @@ static void armctrl_unmask_irq(struct ir
+                                      ARM_LOCAL_GPU_INT_ROUTING);
+               }
+-              writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq),
++              writel_relaxed(FIQ_CONTROL_ENABLE | hwirq_to_fiq(d->hwirq),
+                              intc.base + REG_FIQ_CONTROL);
+       } else {
+               writel_relaxed(HWIRQ_BIT(d->hwirq),
+@@ -201,6 +200,7 @@ static int __init armctrl_of_init(struct
+ {
+       void __iomem *base;
+       int irq = 0, last_irq, b, i;
++      u32 reg;
+       base = of_iomap(node, 0);
+       if (!base)
+@@ -224,6 +224,19 @@ static int __init armctrl_of_init(struct
+                               handle_level_irq);
+                       irq_set_probe(irq);
+               }
++
++              reg = readl_relaxed(intc.enable[b]);
++              if (reg) {
++                      writel_relaxed(reg, intc.disable[b]);
++                      pr_err(FW_BUG "Bootloader left irq enabled: "
++                             "bank %d irq %*pbl\n", b, IRQS_PER_BANK, &reg);
++              }
++      }
++
++      reg = readl_relaxed(base + REG_FIQ_CONTROL);
++      if (reg & FIQ_CONTROL_ENABLE) {
++              writel_relaxed(0, base + REG_FIQ_CONTROL);
++              pr_err(FW_BUG "Bootloader left fiq enabled\n");
+       }
+       last_irq = irq;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0864-dtoverlays-Fixup-imx219-and-imx477-overlays-due-to-p.patch b/target/linux/bcm27xx/patches-5.4/950-0864-dtoverlays-Fixup-imx219-and-imx477-overlays-due-to-p.patch
new file mode 100644 (file)
index 0000000..44ecd49
--- /dev/null
@@ -0,0 +1,42 @@
+From ae906e8cc5152d171ff4d0bf7e668b941a6b1a06 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 1 Jul 2020 18:28:10 +0100
+Subject: [PATCH] dtoverlays: Fixup imx219 and imx477 overlays due to
+ parsing failures
+
+imx219 overlay failed to detect as CSI2 as it was missing any
+of the CSI2 properties on the Unicam end of the configuration.
+Clean up imx477 as well to include all the relevant properties.
+
+Fixes: "dt/dtoverlays: Fix up base DT and overlays for updated Unicam driver"
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/imx219-overlay.dts | 3 +++
+ arch/arm/boot/dts/overlays/imx477-overlay.dts | 2 ++
+ 2 files changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/imx219-overlay.dts
++++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts
+@@ -49,6 +49,9 @@
+                       port {
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&imx219_0>;
++                                      clock-lanes = <0>;
++                                      data-lanes = <1 2>;
++                                      clock-noncontinuous;
+                               };
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/imx477-overlay.dts
++++ b/arch/arm/boot/dts/overlays/imx477-overlay.dts
+@@ -49,7 +49,9 @@
+                       port {
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&imx477_0>;
++                                      clock-lanes = <0>;
+                                       data-lanes = <1 2>;
++                                      clock-noncontinuous;
+                               };
+                       };
+               };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0865-overlays-rpi-ft5406-Fix-boolean-parameters.patch b/target/linux/bcm27xx/patches-5.4/950-0865-overlays-rpi-ft5406-Fix-boolean-parameters.patch
new file mode 100644 (file)
index 0000000..f1daaf2
--- /dev/null
@@ -0,0 +1,27 @@
+From e61f4babc548c69b26f60c93eaa4e20d676db8b8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Sat, 4 Jul 2020 22:19:26 +0100
+Subject: [PATCH] overlays: rpi-ft5406: Fix boolean parameters
+
+An improvement in the automated testing of overlays revealed
+these invalid boolean parameter declarations.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts
+@@ -18,8 +18,8 @@
+       __overrides__ {
+               touchscreen-size-x = <&ts>,"touchscreen-size-x:0";
+               touchscreen-size-y = <&ts>,"touchscreen-size-y:0";
+-              touchscreen-inverted-x = <&ts>,"touchscreen-inverted-x:?";
+-              touchscreen-inverted-y = <&ts>,"touchscreen-inverted-y:?";
+-              touchscreen-swapped-x-y = <&ts>,"touchscreen-swapped-x-y:?";
++              touchscreen-inverted-x = <&ts>,"touchscreen-inverted-x?";
++              touchscreen-inverted-y = <&ts>,"touchscreen-inverted-y?";
++              touchscreen-swapped-x-y = <&ts>,"touchscreen-swapped-x-y?";
+         };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0866-ARM-dts-Copy-kernel-BT-changes-to-CM4.patch b/target/linux/bcm27xx/patches-5.4/950-0866-ARM-dts-Copy-kernel-BT-changes-to-CM4.patch
new file mode 100644 (file)
index 0000000..0c4158b
--- /dev/null
@@ -0,0 +1,29 @@
+From c1037594129cb19e62ea7551b0b4c449a392d883 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 6 Jul 2020 17:53:47 +0100
+Subject: [PATCH] ARM: dts: Copy kernel BT changes to CM4
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -194,6 +194,7 @@
+ // Downstream rpi- changes
+ #include "bcm270x.dtsi"
++#include "bcm271x-rpi-bt.dtsi"
+ / {
+       soc {
+@@ -267,8 +268,6 @@
+ &uart0 {
+       pinctrl-0 = <&uart0_pins &bt_pins>;
+       status = "okay";
+-
+-      /delete-node/ bluetooth;
+ };
+ &uart1 {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0867-ARM-dts-Make-bcm2711-dts-more-like-5.7.patch b/target/linux/bcm27xx/patches-5.4/950-0867-ARM-dts-Make-bcm2711-dts-more-like-5.7.patch
new file mode 100644 (file)
index 0000000..bbe5569
--- /dev/null
@@ -0,0 +1,696 @@
+From 0f02c32b2d27fa5f0b21c67fb5518a36b5234f3a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 7 Jul 2020 09:01:54 +0100
+Subject: [PATCH] ARM: dts: Make bcm2711 dts more like 5.7
+
+The multiple declarations of pixelvalve2 were causing problems for the
+DT checkers. Aligning the dts files closer to the later kernel versions
+avoids some repetition and should make maintenance easier.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 142 ++++++++++++-----------
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts |  69 +----------
+ arch/arm/boot/dts/bcm2711-rpi.dtsi    | 150 +++++++++++++++++++++++-
+ arch/arm/boot/dts/bcm2711.dtsi        | 157 +++-----------------------
+ 4 files changed, 245 insertions(+), 273 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -19,7 +19,9 @@
+       };
+       aliases {
++              emmc2bus = &emmc2bus;
+               ethernet0 = &genet;
++              pcie0 = &pcie0;
+       };
+       leds {
+@@ -30,6 +32,8 @@
+               pwr {
+                       label = "PWR";
+                       gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++                      default-state = "keep";
++                      linux,default-trigger = "default-on";
+               };
+       };
+@@ -70,6 +74,79 @@
+       };
+ };
++&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",
++                        "RGMII_MDIO",
++                        "RGMIO_MDC",
++                        /* Used by BT module */
++                        "CTS0",
++                        "RTS0",
++                        "TXD0",
++                        "RXD0",
++                        /* Used by Wifi */
++                        "SD1_CLK",
++                        "SD1_CMD",
++                        "SD1_DATA0",
++                        "SD1_DATA1",
++                        "SD1_DATA2",
++                        "SD1_DATA3",
++                        /* Shared with SPI flash */
++                        "PWM0_MISO",
++                        "PWM1_MOSI",
++                        "STATUS_LED_G_CLK",
++                        "SPIFLASH_CE_N",
++                        "SDA0",
++                        "SCL0",
++                        "RGMII_RXCLK",
++                        "RGMII_RXCTL",
++                        "RGMII_RXD0",
++                        "RGMII_RXD1",
++                        "RGMII_RXD2",
++                        "RGMII_RXD3",
++                        "RGMII_TXCLK",
++                        "RGMII_TXCTL",
++                        "RGMII_TXD0",
++                        "RGMII_TXD1",
++                        "RGMII_TXD2",
++                        "RGMII_TXD3";
++};
++
+ &pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
+@@ -138,46 +215,6 @@
+       interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ };
+-&vc4 {
+-      status = "okay";
+-};
+-
+-&pixelvalve0 {
+-      status = "okay";
+-};
+-
+-&pixelvalve1 {
+-      status = "okay";
+-};
+-
+-&pixelvalve2 {
+-      status = "okay";
+-};
+-
+-&pixelvalve3 {
+-      status = "okay";
+-};
+-
+-&pixelvalve4 {
+-      status = "okay";
+-};
+-
+-&hdmi0 {
+-      status = "okay";
+-};
+-
+-&ddc0 {
+-      status = "okay";
+-};
+-
+-&hdmi1 {
+-      status = "okay";
+-};
+-
+-&ddc1 {
+-      status = "okay";
+-};
+-
+ // =============================================
+ // Downstream rpi- changes
+@@ -195,8 +232,6 @@
+ #include "bcm283x-rpi-csi1-2lane.dtsi"
+ #include "bcm283x-rpi-i2c0mux_0_44.dtsi"
+-/delete-node/ &emmc2;
+-
+ / {
+       chosen {
+               bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
+@@ -213,29 +248,7 @@
+               i2c4 = &i2c4;
+               i2c5 = &i2c5;
+               i2c6 = &i2c6;
+-              /delete-property/ ethernet;
+               /delete-property/ intc;
+-              pcie0 = &pcie0;
+-              emmc2bus = &emmc2bus;
+-      };
+-
+-      emmc2bus: emmc2bus {
+-              compatible = "simple-bus";
+-              #address-cells = <2>;
+-              #size-cells = <1>;
+-
+-              ranges = <0x0 0x7e000000  0x0 0xfe000000  0x01800000>;
+-              dma-ranges = <0x0 0xc0000000  0x0 0x00000000  0x40000000>;
+-
+-              emmc2: emmc2@7e340000 {
+-                      compatible = "brcm,bcm2711-emmc2";
+-                      status = "okay";
+-                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
+-                      reg = <0x0 0x7e340000 0x100>;
+-                      vqmmc-supply = <&sd_io_1v8_reg>;
+-                      broken-cd;
+-              };
+       };
+       /delete-node/ wifi-pwrseq;
+@@ -557,6 +570,7 @@
+               eth_led0 = <&phy1>,"led-modes:0";
+               eth_led1 = <&phy1>,"led-modes:4";
++              sd_poll_once = <&emmc2>, "non-removable?";
+               spi_dma4 = <&spi0>, "dmas:0=", <&dma40>,
+                          <&spi0>, "dmas:8=", <&dma40>;
+       };
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -19,7 +19,9 @@
+       };
+       aliases {
++              emmc2bus = &emmc2bus;
+               ethernet0 = &genet;
++              pcie0 = &pcie0;
+       };
+       leds {
+@@ -30,6 +32,8 @@
+               pwr {
+                       label = "PWR";
+                       gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++                      default-state = "keep";
++                      linux,default-trigger = "default-on";
+               };
+       };
+@@ -150,46 +154,6 @@
+       interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ };
+-&vc4 {
+-      status = "okay";
+-};
+-
+-&pixelvalve0 {
+-      status = "okay";
+-};
+-
+-&pixelvalve1 {
+-      status = "okay";
+-};
+-
+-&pixelvalve2 {
+-      status = "okay";
+-};
+-
+-&pixelvalve3 {
+-      status = "okay";
+-};
+-
+-&pixelvalve4 {
+-      status = "okay";
+-};
+-
+-&hdmi0 {
+-      status = "okay";
+-};
+-
+-&ddc0 {
+-      status = "okay";
+-};
+-
+-&hdmi1 {
+-      status = "okay";
+-};
+-
+-&ddc1 {
+-      status = "okay";
+-};
+-
+ // =============================================
+ // Downstream rpi- changes
+@@ -208,8 +172,6 @@
+ #include "bcm283x-rpi-csi1-4lane.dtsi"
+ #include "bcm283x-rpi-i2c0mux_0_44.dtsi"
+-/delete-node/ &emmc2;
+-
+ / {
+       chosen {
+               bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
+@@ -226,29 +188,7 @@
+               i2c4 = &i2c4;
+               i2c5 = &i2c5;
+               i2c6 = &i2c6;
+-              /delete-property/ ethernet;
+               /delete-property/ intc;
+-              pcie0 = &pcie0;
+-              emmc2bus = &emmc2bus;
+-      };
+-
+-      emmc2bus: emmc2bus {
+-              compatible = "simple-bus";
+-              #address-cells = <2>;
+-              #size-cells = <1>;
+-
+-              ranges = <0x0 0x7e000000  0x0 0xfe000000  0x01800000>;
+-              dma-ranges = <0x0 0xc0000000  0x0 0x00000000  0x40000000>;
+-
+-              emmc2: emmc2@7e340000 {
+-                      compatible = "brcm,bcm2711-emmc2";
+-                      status = "okay";
+-                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
+-                      reg = <0x0 0x7e340000 0x100>;
+-                      vqmmc-supply = <&sd_io_1v8_reg>;
+-                      broken-cd;
+-              };
+       };
+       /delete-node/ wifi-pwrseq;
+@@ -588,6 +528,7 @@
+                       <&ant2>, "output-high?=off",
+                       <&ant2>, "output-low?=on";
++              sd_poll_once = <&emmc2>, "non-removable?";
+               spi_dma4 = <&spi0>, "dmas:0=", <&dma40>,
+                          <&spi0>, "dmas:8=", <&dma40>;
+       };
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -4,6 +4,129 @@
+ / {
+       soc {
+               /delete-node/ v3d@7ec00000;
++
++              pixelvalve0: pixelvalve@7e206000 {
++                      compatible = "brcm,bcm2711-pixelvalve0";
++                      reg = <0x7e206000 0x100>;
++                      interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              pixelvalve1: pixelvalve@7e207000 {
++                      compatible = "brcm,bcm2711-pixelvalve1";
++                      reg = <0x7e207000 0x100>;
++                      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              pixelvalve2: pixelvalve@7e20a000 {
++                      compatible = "brcm,bcm2711-pixelvalve2";
++                      reg = <0x7e20a000 0x100>;
++                      interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              pixelvalve4: pixelvalve@7e216000 {
++                      compatible = "brcm,bcm2711-pixelvalve4";
++                      reg = <0x7e216000 0x100>;
++                      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              pixelvalve3: pixelvalve@7ec12000 {
++                      compatible = "brcm,bcm2711-pixelvalve3";
++                      reg = <0x7ec12000 0x100>;
++                      interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              dvp: clock@7ef00000 {
++                      compatible = "brcm,brcm2711-dvp";
++                      reg = <0x7ef00000 0x10>;
++                      clocks = <&clk_108MHz>;
++                      #clock-cells = <1>;
++                      #reset-cells = <1>;
++              };
++
++              hdmi0: hdmi@7ef00700 {
++                      compatible = "brcm,bcm2711-hdmi0";
++                      reg = <0x7ef00700 0x300>,
++                            <0x7ef00300 0x200>,
++                            <0x7ef00f00 0x80>,
++                            <0x7ef00f80 0x80>,
++                            <0x7ef01b00 0x200>,
++                            <0x7ef01f00 0x400>,
++                            <0x7ef00200 0x80>,
++                            <0x7ef04300 0x100>,
++                            <0x7ef20000 0x100>,
++                            <0x7ef00100 0x30>;
++                      reg-names = "hdmi",
++                                  "dvp",
++                                  "phy",
++                                  "rm",
++                                  "packet",
++                                  "metadata",
++                                  "csc",
++                                  "cec",
++                                  "hd",
++                                  "intr2";
++                      clocks = <&firmware_clocks 13>;
++                      clock-names = "hdmi";
++                      resets = <&dvp 0>;
++                      ddc = <&ddc0>;
++                      dmas = <&dma 10>;
++                      dma-names = "audio-rx";
++                      interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              ddc0: i2c@7ef04500 {
++                      compatible = "brcm,bcm2711-hdmi-i2c";
++                      reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
++                      reg-names = "bsc", "auto-i2c";
++                      clock-frequency = <97500>;
++                      status = "disabled";
++              };
++
++              hdmi1: hdmi@7ef05700 {
++                      compatible = "brcm,bcm2711-hdmi1";
++                      reg = <0x7ef05700 0x300>,
++                            <0x7ef05300 0x200>,
++                            <0x7ef05f00 0x80>,
++                            <0x7ef05f80 0x80>,
++                            <0x7ef06b00 0x200>,
++                            <0x7ef06f00 0x400>,
++                            <0x7ef00280 0x80>,
++                            <0x7ef09300 0x100>,
++                            <0x7ef20000 0x100>,
++                            <0x7ef00100 0x30>;
++                      reg-names = "hdmi",
++                                  "dvp",
++                                  "phy",
++                                  "rm",
++                                  "packet",
++                                  "metadata",
++                                  "csc",
++                                  "cec",
++                                  "hd",
++                                  "intr2";
++                      ddc = <&ddc1>;
++                      clocks = <&firmware_clocks 13>;
++                      clock-names = "hdmi";
++                      resets = <&dvp 1>;
++                      dmas = <&dma 17>;
++                      dma-names = "audio-rx";
++                      interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
++                      status = "disabled";
++              };
++
++              ddc1: i2c@7ef09500 {
++                      compatible = "brcm,bcm2711-hdmi-i2c";
++                      reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
++                      reg-names = "bsc", "auto-i2c";
++                      clock-frequency = <97500>;
++                      status = "disabled";
++              };
+       };
+       __overrides__ {
+@@ -42,22 +165,33 @@
+       scb: scb {
+            /* Add a label */
+       };
+-};
+-&cma {
+-      /* Limit cma to the lower 768MB to allow room for HIGHMEM on 32-bit */
+-      alloc-ranges = <0x0 0x00000000 0x30000000>;
++      vc4: gpu {
++              compatible = "brcm,bcm2711-vc5";
++              status = "disabled";
++      };
++
++      clk_108MHz: clk-108M {
++              #clock-cells = <0>;
++              compatible = "fixed-clock";
++              clock-frequency = <108000000>;
++              clock-output-names = "108MHz-clock";
++      };
+ };
+ &soc {
+       /delete-node/ audio;
+ };
++&cma {
++      /* Limit cma to the lower 768MB to allow room for HIGHMEM on 32-bit */
++      alloc-ranges = <0x0 0x00000000 0x30000000>;
++};
++
+ &scb {
+       ranges = <0x0 0x7c000000  0x0 0xfc000000  0x0 0x03800000>,
+                <0x0 0x40000000  0x0 0xff800000  0x0 0x00800000>,
+-               <0x6 0x00000000  0x6 0x00000000  0x0 0x40000000>,
+-               <0x0 0x00000000  0x0 0x00000000  0x0 0xfc000000>;
++               <0x6 0x00000000  0x6 0x00000000  0x0 0x40000000>;
+       dma-ranges = <0x0 0x00000000  0x0 0x00000000  0x0 0xfc000000>,
+                    <0x1 0x00000000  0x1 0x00000000  0x1 0x00000000>;
+@@ -171,6 +305,10 @@
+       compatible = "brcm,bcm2711-genet-v5", "brcm,genet-v5";
+ };
++&hvs {
++      clocks = <&firmware_clocks 4>;
++};
++
+ &firmware {
+       firmware_clocks: clocks {
+               compatible = "raspberrypi,firmware-clocks";
+--- a/arch/arm/boot/dts/bcm2711.dtsi
++++ b/arch/arm/boot/dts/bcm2711.dtsi
+@@ -12,18 +12,6 @@
+       interrupt-parent = <&gicv2>;
+-      vc4: gpu {
+-              compatible = "brcm,bcm2711-vc5";
+-              status = "disabled";
+-      };
+-
+-      clk_108MHz: clk-108M {
+-              #clock-cells = <0>;
+-              compatible = "fixed-clock";
+-              clock-frequency = <108000000>;
+-              clock-output-names = "108MHz-clock";
+-      };
+-
+       soc {
+               /*
+                * Defined ranges:
+@@ -245,27 +233,6 @@
+                       status = "disabled";
+               };
+-              pixelvalve0: pixelvalve@7e206000 {
+-                      compatible = "brcm,bcm2711-pixelvalve0";
+-                      reg = <0x7e206000 0x100>;
+-                      interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
+-
+-              pixelvalve1: pixelvalve@7e207000 {
+-                      compatible = "brcm,bcm2711-pixelvalve1";
+-                      reg = <0x7e207000 0x100>;
+-                      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
+-
+-              pixelvalve2: pixelvalve@7e20a000 {
+-                      compatible = "brcm,bcm2711-pixelvalve2";
+-                      reg = <0x7e20a000 0x100>;
+-                      interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
+-
+               pwm1: pwm@7e20c800 {
+                       compatible = "brcm,bcm2835-pwm";
+                       reg = <0x7e20c800 0x28>;
+@@ -276,118 +243,30 @@
+                       status = "disabled";
+               };
+-              pixelvalve4: pixelvalve@7e216000 {
+-                      compatible = "brcm,bcm2711-pixelvalve4";
+-                      reg = <0x7e216000 0x100>;
+-                      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
+-
+-              emmc2: emmc2@7e340000 {
+-                      compatible = "brcm,bcm2711-emmc2";
+-                      reg = <0x7e340000 0x100>;
+-                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
+-                      status = "disabled";
+-              };
+-
+               hvs@7e400000 {
+-                      clocks = <&firmware_clocks 4>;
+                       interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+               };
++      };
+-              pixelvalve3: pixelvalve@7ec12000 {
+-                      compatible = "brcm,bcm2711-pixelvalve3";
+-                      reg = <0x7ec12000 0x100>;
+-                      interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
++      /*
++       * emmc2 has different DMA constraints based on SoC revisions. It was
++       * moved into its own bus, so as for RPi4's firmware to update them.
++       * The firmware will find whether the emmc2bus alias is defined, and if
++       * so, it'll edit the dma-ranges property below accordingly.
++       */
++      emmc2bus: emmc2bus {
++              compatible = "simple-bus";
++              #address-cells = <2>;
++              #size-cells = <1>;
+-              dvp: clock@7ef00000 {
+-                      compatible = "brcm,brcm2711-dvp";
+-                      reg = <0x7ef00000 0x10>;
+-                      clocks = <&clk_108MHz>;
+-                      #clock-cells = <1>;
+-                      #reset-cells = <1>;
+-              };
++              ranges = <0x0 0x7e000000  0x0 0xfe000000  0x01800000>;
++              dma-ranges = <0x0 0xc0000000  0x0 0x00000000  0x40000000>;
+-              hdmi0: hdmi@7ef00700 {
+-                      compatible = "brcm,bcm2711-hdmi0";
+-                      reg = <0x7ef00700 0x300>,
+-                            <0x7ef00300 0x200>,
+-                            <0x7ef00f00 0x80>,
+-                            <0x7ef00f80 0x80>,
+-                            <0x7ef01b00 0x200>,
+-                            <0x7ef01f00 0x400>,
+-                            <0x7ef00200 0x80>,
+-                            <0x7ef04300 0x100>,
+-                            <0x7ef20000 0x100>,
+-                            <0x7ef00100 0x30>;
+-                      reg-names = "hdmi",
+-                                  "dvp",
+-                                  "phy",
+-                                  "rm",
+-                                  "packet",
+-                                  "metadata",
+-                                  "csc",
+-                                  "cec",
+-                                  "hd",
+-                                  "intr2";
+-                      clocks = <&firmware_clocks 13>;
+-                      clock-names = "hdmi";
+-                      resets = <&dvp 0>;
+-                      ddc = <&ddc0>;
+-                      dmas = <&dma 10>;
+-                      dma-names = "audio-rx";
+-                      interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
+-
+-              ddc0: i2c@7ef04500 {
+-                      compatible = "brcm,bcm2711-hdmi-i2c";
+-                      reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
+-                      reg-names = "bsc", "auto-i2c";
+-                      clock-frequency = <97500>;
+-                      status = "disabled";
+-              };
+-
+-              hdmi1: hdmi@7ef05700 {
+-                      compatible = "brcm,bcm2711-hdmi1";
+-                      reg = <0x7ef05700 0x300>,
+-                            <0x7ef05300 0x200>,
+-                            <0x7ef05f00 0x80>,
+-                            <0x7ef05f80 0x80>,
+-                            <0x7ef06b00 0x200>,
+-                            <0x7ef06f00 0x400>,
+-                            <0x7ef00280 0x80>,
+-                            <0x7ef09300 0x100>,
+-                            <0x7ef20000 0x100>,
+-                            <0x7ef00100 0x30>;
+-                      reg-names = "hdmi",
+-                                  "dvp",
+-                                  "phy",
+-                                  "rm",
+-                                  "packet",
+-                                  "metadata",
+-                                  "csc",
+-                                  "cec",
+-                                  "hd",
+-                                  "intr2";
+-                      ddc = <&ddc1>;
+-                      clocks = <&firmware_clocks 13>;
+-                      clock-names = "hdmi";
+-                      resets = <&dvp 1>;
+-                      dmas = <&dma 17>;
+-                      dma-names = "audio-rx";
+-                      interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+-                      status = "disabled";
+-              };
+-
+-              ddc1: i2c@7ef09500 {
+-                      compatible = "brcm,bcm2711-hdmi-i2c";
+-                      reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
+-                      reg-names = "bsc", "auto-i2c";
+-                      clock-frequency = <97500>;
++              emmc2: emmc2@7e340000 {
++                      compatible = "brcm,bcm2711-emmc2";
++                      reg = <0x0 0x7e340000 0x100>;
++                      interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&clocks BCM2711_CLOCK_EMMC2>;
+                       status = "disabled";
+               };
+       };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0868-bcm2835-dma-Add-NO_WAIT_RESP-flag.patch b/target/linux/bcm27xx/patches-5.4/950-0868-bcm2835-dma-Add-NO_WAIT_RESP-flag.patch
new file mode 100644 (file)
index 0000000..8fc7069
--- /dev/null
@@ -0,0 +1,54 @@
+From 8c070947d0d9ef7f890eeff329d4deb1c393ef87 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 1 Jul 2020 20:28:27 +0100
+Subject: [PATCH] bcm2835-dma: Add NO_WAIT_RESP flag
+
+Use bit 27 of the dreq value (the second cell of the DT DMA descriptor)
+to request that the WAIT_RESP bit is not set.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/dma/bcm2835-dma.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -167,6 +167,11 @@ struct bcm2835_desc {
+ #define BCM2835_DMA_WAIT(x)   ((x & 31) << 21) /* add DMA-wait cycles */
+ #define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */
++/* A fake bit to request that the driver doesn't set the WAIT_RESP bit. */
++#define BCM2835_DMA_NO_WAIT_RESP BIT(27)
++#define WAIT_RESP(x) ((x & BCM2835_DMA_NO_WAIT_RESP) ? \
++                    0 : BCM2835_DMA_WAIT_RESP)
++
+ /* debug register bits */
+ #define BCM2835_DMA_DEBUG_LAST_NOT_SET_ERR    BIT(0)
+ #define BCM2835_DMA_DEBUG_FIFO_ERR            BIT(1)
+@@ -845,7 +850,7 @@ static struct dma_async_tx_descriptor *b
+       struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+       struct bcm2835_desc *d;
+       u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC;
+-      u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP;
++      u32 extra = BCM2835_DMA_INT_EN | WAIT_RESP(c->dreq);
+       size_t max_len = bcm2835_dma_max_frame_length(c);
+       size_t frames;
+@@ -875,7 +880,7 @@ static struct dma_async_tx_descriptor *b
+       struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+       struct bcm2835_desc *d;
+       dma_addr_t src = 0, dst = 0;
+-      u32 info = BCM2835_DMA_WAIT_RESP;
++      u32 info = WAIT_RESP(c->dreq);
+       u32 extra = BCM2835_DMA_INT_EN;
+       size_t frames;
+@@ -937,7 +942,7 @@ static struct dma_async_tx_descriptor *b
+       struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+       struct bcm2835_desc *d;
+       dma_addr_t src, dst;
+-      u32 info = BCM2835_DMA_WAIT_RESP;
++      u32 info = WAIT_RESP(c->dreq);
+       u32 extra = 0;
+       size_t max_len = bcm2835_dma_max_frame_length(c);
+       size_t frames;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0869-ARM-dts-Restore-the-old-2711-scb-ranges-property.patch b/target/linux/bcm27xx/patches-5.4/950-0869-ARM-dts-Restore-the-old-2711-scb-ranges-property.patch
new file mode 100644 (file)
index 0000000..614b149
--- /dev/null
@@ -0,0 +1,24 @@
+From f2233a2a1baf7036469e5291b06457311120dfb4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 7 Jul 2020 14:08:55 +0100
+Subject: [PATCH] ARM: dts: Restore the old 2711 scb ranges property
+
+The back-ported value breaks PCIe.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -191,7 +191,8 @@
+ &scb {
+       ranges = <0x0 0x7c000000  0x0 0xfc000000  0x0 0x03800000>,
+                <0x0 0x40000000  0x0 0xff800000  0x0 0x00800000>,
+-               <0x6 0x00000000  0x6 0x00000000  0x0 0x40000000>;
++               <0x6 0x00000000  0x6 0x00000000  0x0 0x40000000>,
++               <0x0 0x00000000  0x0 0x00000000  0x0 0xfc000000>;
+       dma-ranges = <0x0 0x00000000  0x0 0x00000000  0x0 0xfc000000>,
+                    <0x1 0x00000000  0x1 0x00000000  0x1 0x00000000>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0870-media-i2c-add-ov9281-driver.patch b/target/linux/bcm27xx/patches-5.4/950-0870-media-i2c-add-ov9281-driver.patch
new file mode 100644 (file)
index 0000000..c48a146
--- /dev/null
@@ -0,0 +1,1218 @@
+From ca6aba3a4bf358b763d0e508df95455de3ae992c Mon Sep 17 00:00:00 2001
+From: Zefa Chen <zefa.chen@rock-chips.com>
+Date: Fri, 17 May 2019 18:23:03 +0800
+Subject: [PATCH] media: i2c: add ov9281 driver.
+
+Change-Id: I7b77250bbc56d2f861450cf77271ad15f9b88ab1
+Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
+---
+ drivers/media/i2c/Kconfig  |   11 +
+ drivers/media/i2c/Makefile |    1 +
+ drivers/media/i2c/ov9281.c | 1171 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1183 insertions(+)
+ create mode 100644 drivers/media/i2c/ov9281.c
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -855,6 +855,17 @@ config VIDEO_OV9640
+         This is a Video4Linux2 sensor driver for the OmniVision
+         OV9640 camera sensor.
++config VIDEO_OV9281
++      tristate "OmniVision OV9281 sensor support"
++      depends on I2C && VIDEO_V4L2
++      depends on MEDIA_CAMERA_SUPPORT
++      help
++        This is a Video4Linux2 sensor-level driver for the OmniVision
++        OV9281 camera.
++
++        To compile this driver as a module, choose M here: the
++        module will be called ov9281.
++
+ config VIDEO_OV9650
+       tristate "OmniVision OV9650/OV9652 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+--- a/drivers/media/i2c/Makefile
++++ b/drivers/media/i2c/Makefile
+@@ -79,6 +79,7 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+ obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
+ obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
+ obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
++obj-$(CONFIG_VIDEO_OV9281) += ov9281.o
+ obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
+ obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
+ obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
+--- /dev/null
++++ b/drivers/media/i2c/ov9281.c
+@@ -0,0 +1,1171 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * ov9281 driver
++ *
++ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
++ */
++
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/gpio/consumer.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/pm_runtime.h>
++#include <linux/regulator/consumer.h>
++#include <linux/sysfs.h>
++#include <linux/slab.h>
++#include <linux/rk-camera-module.h>
++#include <media/media-entity.h>
++#include <media/v4l2-async.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-subdev.h>
++#include <linux/pinctrl/consumer.h>
++
++#define DRIVER_VERSION                        KERNEL_VERSION(0, 0x01, 0x0)
++
++#ifndef V4L2_CID_DIGITAL_GAIN
++#define V4L2_CID_DIGITAL_GAIN         V4L2_CID_GAIN
++#endif
++
++#define OV9281_LINK_FREQ_400MHZ               400000000
++/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
++#define OV9281_PIXEL_RATE             (OV9281_LINK_FREQ_400MHZ * 2 * 2 / 10)
++#define OV9281_XVCLK_FREQ             24000000
++
++#define CHIP_ID                               0x9281
++#define OV9281_REG_CHIP_ID            0x300a
++
++#define OV9281_REG_CTRL_MODE          0x0100
++#define OV9281_MODE_SW_STANDBY                0x0
++#define OV9281_MODE_STREAMING         BIT(0)
++
++#define OV9281_REG_EXPOSURE           0x3500
++#define       OV9281_EXPOSURE_MIN             4
++#define       OV9281_EXPOSURE_STEP            1
++#define OV9281_VTS_MAX                        0x7fff
++
++#define OV9281_REG_GAIN_H             0x3508
++#define OV9281_REG_GAIN_L             0x3509
++#define OV9281_GAIN_H_MASK            0x07
++#define OV9281_GAIN_H_SHIFT           8
++#define OV9281_GAIN_L_MASK            0xff
++#define OV9281_GAIN_MIN                       0x10
++#define OV9281_GAIN_MAX                       0xf8
++#define OV9281_GAIN_STEP              1
++#define OV9281_GAIN_DEFAULT           0x10
++
++#define OV9281_REG_TEST_PATTERN               0x5e00
++#define OV9281_TEST_PATTERN_ENABLE    0x80
++#define OV9281_TEST_PATTERN_DISABLE   0x0
++
++#define OV9281_REG_VTS                        0x380e
++
++#define REG_NULL                      0xFFFF
++
++#define OV9281_REG_VALUE_08BIT                1
++#define OV9281_REG_VALUE_16BIT                2
++#define OV9281_REG_VALUE_24BIT                3
++
++#define OV9281_LANES                  2
++#define OV9281_BITS_PER_SAMPLE                10
++
++#define OF_CAMERA_PINCTRL_STATE_DEFAULT       "rockchip,camera_default"
++#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
++
++#define OV9281_NAME                   "ov9281"
++
++static const char * const ov9281_supply_names[] = {
++      "avdd",         /* Analog power */
++      "dovdd",        /* Digital I/O power */
++      "dvdd",         /* Digital core power */
++};
++
++#define OV9281_NUM_SUPPLIES ARRAY_SIZE(ov9281_supply_names)
++
++struct regval {
++      u16 addr;
++      u8 val;
++};
++
++struct ov9281_mode {
++      u32 width;
++      u32 height;
++      u32 max_fps;
++      u32 hts_def;
++      u32 vts_def;
++      u32 exp_def;
++      const struct regval *reg_list;
++};
++
++struct ov9281 {
++      struct i2c_client       *client;
++      struct clk              *xvclk;
++      struct gpio_desc        *reset_gpio;
++      struct gpio_desc        *pwdn_gpio;
++      struct regulator_bulk_data supplies[OV9281_NUM_SUPPLIES];
++
++      struct pinctrl          *pinctrl;
++      struct pinctrl_state    *pins_default;
++      struct pinctrl_state    *pins_sleep;
++
++      struct v4l2_subdev      subdev;
++      struct media_pad        pad;
++      struct v4l2_ctrl_handler ctrl_handler;
++      struct v4l2_ctrl        *exposure;
++      struct v4l2_ctrl        *anal_gain;
++      struct v4l2_ctrl        *digi_gain;
++      struct v4l2_ctrl        *hblank;
++      struct v4l2_ctrl        *vblank;
++      struct v4l2_ctrl        *test_pattern;
++      struct mutex            mutex;
++      bool                    streaming;
++      bool                    power_on;
++      const struct ov9281_mode *cur_mode;
++      u32                     module_index;
++      const char              *module_facing;
++      const char              *module_name;
++      const char              *len_name;
++};
++
++#define to_ov9281(sd) container_of(sd, struct ov9281, subdev)
++
++/*
++ * Xclk 24Mhz
++ */
++static const struct regval ov9281_global_regs[] = {
++      {REG_NULL, 0x00},
++};
++
++/*
++ * Xclk 24Mhz
++ * max_framerate 120fps
++ * mipi_datarate per lane 800Mbps
++ */
++static const struct regval ov9281_1280x800_regs[] = {
++      {0x0103, 0x01},
++      {0x0302, 0x32},
++      {0x030d, 0x50},
++      {0x030e, 0x02},
++      {0x3001, 0x00},
++      {0x3004, 0x00},
++      {0x3005, 0x00},
++      {0x3006, 0x04},
++      {0x3011, 0x0a},
++      {0x3013, 0x18},
++      {0x3022, 0x01},
++      {0x3023, 0x00},
++      {0x302c, 0x00},
++      {0x302f, 0x00},
++      {0x3030, 0x04},
++      {0x3039, 0x32},
++      {0x303a, 0x00},
++      {0x303f, 0x01},
++      {0x3500, 0x00},
++      {0x3501, 0x2a},
++      {0x3502, 0x90},
++      {0x3503, 0x08},
++      {0x3505, 0x8c},
++      {0x3507, 0x03},
++      {0x3508, 0x00},
++      {0x3509, 0x10},
++      {0x3610, 0x80},
++      {0x3611, 0xa0},
++      {0x3620, 0x6f},
++      {0x3632, 0x56},
++      {0x3633, 0x78},
++      {0x3662, 0x05},
++      {0x3666, 0x00},
++      {0x366f, 0x5a},
++      {0x3680, 0x84},
++      {0x3712, 0x80},
++      {0x372d, 0x22},
++      {0x3731, 0x80},
++      {0x3732, 0x30},
++      {0x3778, 0x00},
++      {0x377d, 0x22},
++      {0x3788, 0x02},
++      {0x3789, 0xa4},
++      {0x378a, 0x00},
++      {0x378b, 0x4a},
++      {0x3799, 0x20},
++      {0x3800, 0x00},
++      {0x3801, 0x00},
++      {0x3802, 0x00},
++      {0x3803, 0x00},
++      {0x3804, 0x05},
++      {0x3805, 0x0f},
++      {0x3806, 0x03},
++      {0x3807, 0x2f},
++      {0x3808, 0x05},
++      {0x3809, 0x00},
++      {0x380a, 0x03},
++      {0x380b, 0x20},
++      {0x380c, 0x02},
++      {0x380d, 0xd8},
++      {0x380e, 0x03},
++      {0x380f, 0x8e},
++      {0x3810, 0x00},
++      {0x3811, 0x08},
++      {0x3812, 0x00},
++      {0x3813, 0x08},
++      {0x3814, 0x11},
++      {0x3815, 0x11},
++      {0x3820, 0x40},
++      {0x3821, 0x00},
++      {0x3881, 0x42},
++      {0x38b1, 0x00},
++      {0x3920, 0xff},
++      {0x4003, 0x40},
++      {0x4008, 0x04},
++      {0x4009, 0x0b},
++      {0x400c, 0x00},
++      {0x400d, 0x07},
++      {0x4010, 0x40},
++      {0x4043, 0x40},
++      {0x4307, 0x30},
++      {0x4317, 0x00},
++      {0x4501, 0x00},
++      {0x4507, 0x00},
++      {0x4509, 0x00},
++      {0x450a, 0x08},
++      {0x4601, 0x04},
++      {0x470f, 0x00},
++      {0x4f07, 0x00},
++      {0x4800, 0x00},
++      {0x5000, 0x9f},
++      {0x5001, 0x00},
++      {0x5e00, 0x00},
++      {0x5d00, 0x07},
++      {0x5d01, 0x00},
++      {REG_NULL, 0x00},
++};
++
++static const struct ov9281_mode supported_modes[] = {
++      {
++              .width = 1280,
++              .height = 800,
++              .max_fps = 120,
++              .exp_def = 0x0320,
++              .hts_def = 0x0b60,//0x2d8*4
++              .vts_def = 0x038e,
++              .reg_list = ov9281_1280x800_regs,
++      },
++};
++
++static const s64 link_freq_menu_items[] = {
++      OV9281_LINK_FREQ_400MHZ
++};
++
++static const char * const ov9281_test_pattern_menu[] = {
++      "Disabled",
++      "Vertical Color Bar Type 1",
++      "Vertical Color Bar Type 2",
++      "Vertical Color Bar Type 3",
++      "Vertical Color Bar Type 4"
++};
++
++/* Write registers up to 4 at a time */
++static int ov9281_write_reg(struct i2c_client *client, u16 reg,
++                          u32 len, u32 val)
++{
++      u32 buf_i, val_i;
++      u8 buf[6];
++      u8 *val_p;
++      __be32 val_be;
++
++      if (len > 4)
++              return -EINVAL;
++
++      buf[0] = reg >> 8;
++      buf[1] = reg & 0xff;
++
++      val_be = cpu_to_be32(val);
++      val_p = (u8 *)&val_be;
++      buf_i = 2;
++      val_i = 4 - len;
++
++      while (val_i < 4)
++              buf[buf_i++] = val_p[val_i++];
++
++      if (i2c_master_send(client, buf, len + 2) != len + 2)
++              return -EIO;
++
++      return 0;
++}
++
++static int ov9281_write_array(struct i2c_client *client,
++                            const struct regval *regs)
++{
++      u32 i;
++      int ret = 0;
++
++      for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
++              ret = ov9281_write_reg(client, regs[i].addr,
++                                     OV9281_REG_VALUE_08BIT, regs[i].val);
++
++      return ret;
++}
++
++/* Read registers up to 4 at a time */
++static int ov9281_read_reg(struct i2c_client *client, u16 reg, unsigned int len,
++                         u32 *val)
++{
++      struct i2c_msg msgs[2];
++      u8 *data_be_p;
++      __be32 data_be = 0;
++      __be16 reg_addr_be = cpu_to_be16(reg);
++      int ret;
++
++      if (len > 4 || !len)
++              return -EINVAL;
++
++      data_be_p = (u8 *)&data_be;
++      /* Write register address */
++      msgs[0].addr = client->addr;
++      msgs[0].flags = 0;
++      msgs[0].len = 2;
++      msgs[0].buf = (u8 *)&reg_addr_be;
++
++      /* Read data from register */
++      msgs[1].addr = client->addr;
++      msgs[1].flags = I2C_M_RD;
++      msgs[1].len = len;
++      msgs[1].buf = &data_be_p[4 - len];
++
++      ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
++      if (ret != ARRAY_SIZE(msgs))
++              return -EIO;
++
++      *val = be32_to_cpu(data_be);
++
++      return 0;
++}
++
++static int ov9281_get_reso_dist(const struct ov9281_mode *mode,
++                              struct v4l2_mbus_framefmt *framefmt)
++{
++      return abs(mode->width - framefmt->width) +
++             abs(mode->height - framefmt->height);
++}
++
++static const struct ov9281_mode *
++ov9281_find_best_fit(struct v4l2_subdev_format *fmt)
++{
++      struct v4l2_mbus_framefmt *framefmt = &fmt->format;
++      int dist;
++      int cur_best_fit = 0;
++      int cur_best_fit_dist = -1;
++      unsigned int i;
++
++      for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
++              dist = ov9281_get_reso_dist(&supported_modes[i], framefmt);
++              if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
++                      cur_best_fit_dist = dist;
++                      cur_best_fit = i;
++              }
++      }
++
++      return &supported_modes[cur_best_fit];
++}
++
++static int ov9281_set_fmt(struct v4l2_subdev *sd,
++                        struct v4l2_subdev_pad_config *cfg,
++                        struct v4l2_subdev_format *fmt)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      const struct ov9281_mode *mode;
++      s64 h_blank, vblank_def;
++
++      mutex_lock(&ov9281->mutex);
++
++      mode = ov9281_find_best_fit(fmt);
++      fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
++      fmt->format.width = mode->width;
++      fmt->format.height = mode->height;
++      fmt->format.field = V4L2_FIELD_NONE;
++      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
++#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
++              *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
++#else
++              mutex_unlock(&ov9281->mutex);
++              return -ENOTTY;
++#endif
++      } else {
++              ov9281->cur_mode = mode;
++              h_blank = mode->hts_def - mode->width;
++              __v4l2_ctrl_modify_range(ov9281->hblank, h_blank,
++                                       h_blank, 1, h_blank);
++              vblank_def = mode->vts_def - mode->height;
++              __v4l2_ctrl_modify_range(ov9281->vblank, vblank_def,
++                                       OV9281_VTS_MAX - mode->height,
++                                       1, vblank_def);
++      }
++
++      mutex_unlock(&ov9281->mutex);
++
++      return 0;
++}
++
++static int ov9281_get_fmt(struct v4l2_subdev *sd,
++                        struct v4l2_subdev_pad_config *cfg,
++                        struct v4l2_subdev_format *fmt)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      const struct ov9281_mode *mode = ov9281->cur_mode;
++
++      mutex_lock(&ov9281->mutex);
++      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
++#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
++              fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
++#else
++              mutex_unlock(&ov9281->mutex);
++              return -ENOTTY;
++#endif
++      } else {
++              fmt->format.width = mode->width;
++              fmt->format.height = mode->height;
++              fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
++              fmt->format.field = V4L2_FIELD_NONE;
++      }
++      mutex_unlock(&ov9281->mutex);
++
++      return 0;
++}
++
++static int ov9281_enum_mbus_code(struct v4l2_subdev *sd,
++                               struct v4l2_subdev_pad_config *cfg,
++                               struct v4l2_subdev_mbus_code_enum *code)
++{
++      if (code->index != 0)
++              return -EINVAL;
++      code->code = MEDIA_BUS_FMT_Y10_1X10;
++
++      return 0;
++}
++
++static int ov9281_enum_frame_sizes(struct v4l2_subdev *sd,
++                                 struct v4l2_subdev_pad_config *cfg,
++                                 struct v4l2_subdev_frame_size_enum *fse)
++{
++      if (fse->index >= ARRAY_SIZE(supported_modes))
++              return -EINVAL;
++
++      if (fse->code != MEDIA_BUS_FMT_Y10_1X10)
++              return -EINVAL;
++
++      fse->min_width  = supported_modes[fse->index].width;
++      fse->max_width  = supported_modes[fse->index].width;
++      fse->max_height = supported_modes[fse->index].height;
++      fse->min_height = supported_modes[fse->index].height;
++
++      return 0;
++}
++
++static int ov9281_enable_test_pattern(struct ov9281 *ov9281, u32 pattern)
++{
++      u32 val;
++
++      if (pattern)
++              val = (pattern - 1) | OV9281_TEST_PATTERN_ENABLE;
++      else
++              val = OV9281_TEST_PATTERN_DISABLE;
++
++      return ov9281_write_reg(ov9281->client, OV9281_REG_TEST_PATTERN,
++                              OV9281_REG_VALUE_08BIT, val);
++}
++
++static int OV9281_g_frame_interval(struct v4l2_subdev *sd,
++                                 struct v4l2_subdev_frame_interval *fi)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      const struct ov9281_mode *mode = ov9281->cur_mode;
++
++      mutex_lock(&ov9281->mutex);
++      fi->interval.numerator = 10000;
++      fi->interval.denominator = mode->max_fps * 10000;
++      mutex_unlock(&ov9281->mutex);
++
++      return 0;
++}
++
++static void ov9281_get_module_inf(struct ov9281 *ov9281,
++                                struct rkmodule_inf *inf)
++{
++      memset(inf, 0, sizeof(*inf));
++      strlcpy(inf->base.sensor, OV9281_NAME, sizeof(inf->base.sensor));
++      strlcpy(inf->base.module, ov9281->module_name,
++              sizeof(inf->base.module));
++      strlcpy(inf->base.lens, ov9281->len_name, sizeof(inf->base.lens));
++}
++
++static long ov9281_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      long ret = 0;
++
++      switch (cmd) {
++      case RKMODULE_GET_MODULE_INFO:
++              ov9281_get_module_inf(ov9281, (struct rkmodule_inf *)arg);
++              break;
++      default:
++              ret = -ENOIOCTLCMD;
++              break;
++      }
++
++      return ret;
++}
++
++#ifdef CONFIG_COMPAT
++static long ov9281_compat_ioctl32(struct v4l2_subdev *sd,
++                                unsigned int cmd, unsigned long arg)
++{
++      void __user *up = compat_ptr(arg);
++      struct rkmodule_inf *inf;
++      struct rkmodule_awb_cfg *cfg;
++      long ret;
++
++      switch (cmd) {
++      case RKMODULE_GET_MODULE_INFO:
++              inf = kzalloc(sizeof(*inf), GFP_KERNEL);
++              if (!inf) {
++                      ret = -ENOMEM;
++                      return ret;
++              }
++
++              ret = ov9281_ioctl(sd, cmd, inf);
++              if (!ret)
++                      ret = copy_to_user(up, inf, sizeof(*inf));
++              kfree(inf);
++              break;
++      case RKMODULE_AWB_CFG:
++              cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
++              if (!cfg) {
++                      ret = -ENOMEM;
++                      return ret;
++              }
++
++              ret = copy_from_user(cfg, up, sizeof(*cfg));
++              if (!ret)
++                      ret = ov9281_ioctl(sd, cmd, cfg);
++              kfree(cfg);
++              break;
++      default:
++              ret = -ENOIOCTLCMD;
++              break;
++      }
++
++      return ret;
++}
++#endif
++
++static int __ov9281_start_stream(struct ov9281 *ov9281)
++{
++      int ret;
++
++      ret = ov9281_write_array(ov9281->client, ov9281->cur_mode->reg_list);
++      if (ret)
++              return ret;
++
++      /* In case these controls are set before streaming */
++      mutex_unlock(&ov9281->mutex);
++      ret = v4l2_ctrl_handler_setup(&ov9281->ctrl_handler);
++      mutex_lock(&ov9281->mutex);
++      if (ret)
++              return ret;
++
++      return ov9281_write_reg(ov9281->client, OV9281_REG_CTRL_MODE,
++                              OV9281_REG_VALUE_08BIT, OV9281_MODE_STREAMING);
++}
++
++static int __ov9281_stop_stream(struct ov9281 *ov9281)
++{
++      return ov9281_write_reg(ov9281->client, OV9281_REG_CTRL_MODE,
++                              OV9281_REG_VALUE_08BIT, OV9281_MODE_SW_STANDBY);
++}
++
++static int ov9281_s_stream(struct v4l2_subdev *sd, int on)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      struct i2c_client *client = ov9281->client;
++      int ret = 0;
++
++      mutex_lock(&ov9281->mutex);
++      on = !!on;
++      if (on == ov9281->streaming)
++              goto unlock_and_return;
++
++      if (on) {
++              ret = pm_runtime_get_sync(&client->dev);
++              if (ret < 0) {
++                      pm_runtime_put_noidle(&client->dev);
++                      goto unlock_and_return;
++              }
++
++              ret = __ov9281_start_stream(ov9281);
++              if (ret) {
++                      v4l2_err(sd, "start stream failed while write regs\n");
++                      pm_runtime_put(&client->dev);
++                      goto unlock_and_return;
++              }
++      } else {
++              __ov9281_stop_stream(ov9281);
++              pm_runtime_put(&client->dev);
++      }
++
++      ov9281->streaming = on;
++
++unlock_and_return:
++      mutex_unlock(&ov9281->mutex);
++
++      return ret;
++}
++
++static int ov9281_s_power(struct v4l2_subdev *sd, int on)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      struct i2c_client *client = ov9281->client;
++      int ret = 0;
++
++      mutex_lock(&ov9281->mutex);
++
++      /* If the power state is not modified - no work to do. */
++      if (ov9281->power_on == !!on)
++              goto unlock_and_return;
++
++      if (on) {
++              ret = pm_runtime_get_sync(&client->dev);
++              if (ret < 0) {
++                      pm_runtime_put_noidle(&client->dev);
++                      goto unlock_and_return;
++              }
++              ret = ov9281_write_array(ov9281->client, ov9281_global_regs);
++              if (ret) {
++                      v4l2_err(sd, "could not set init registers\n");
++                      pm_runtime_put_noidle(&client->dev);
++                      goto unlock_and_return;
++              }
++              ov9281->power_on = true;
++      } else {
++              pm_runtime_put(&client->dev);
++              ov9281->power_on = false;
++      }
++
++unlock_and_return:
++      mutex_unlock(&ov9281->mutex);
++
++      return ret;
++}
++
++/* Calculate the delay in us by clock rate and clock cycles */
++static inline u32 ov9281_cal_delay(u32 cycles)
++{
++      return DIV_ROUND_UP(cycles, OV9281_XVCLK_FREQ / 1000 / 1000);
++}
++
++static int __ov9281_power_on(struct ov9281 *ov9281)
++{
++      int ret;
++      u32 delay_us;
++      struct device *dev = &ov9281->client->dev;
++
++      if (!IS_ERR_OR_NULL(ov9281->pins_default)) {
++              ret = pinctrl_select_state(ov9281->pinctrl,
++                                         ov9281->pins_default);
++              if (ret < 0)
++                      dev_err(dev, "could not set pins\n");
++      }
++
++      ret = clk_prepare_enable(ov9281->xvclk);
++      if (ret < 0) {
++              dev_err(dev, "Failed to enable xvclk\n");
++              return ret;
++      }
++
++      if (!IS_ERR(ov9281->reset_gpio))
++              gpiod_set_value_cansleep(ov9281->reset_gpio, 0);
++
++      ret = regulator_bulk_enable(OV9281_NUM_SUPPLIES, ov9281->supplies);
++      if (ret < 0) {
++              dev_err(dev, "Failed to enable regulators\n");
++              goto disable_clk;
++      }
++
++      if (!IS_ERR(ov9281->reset_gpio))
++              gpiod_set_value_cansleep(ov9281->reset_gpio, 1);
++
++      usleep_range(500, 1000);
++      if (!IS_ERR(ov9281->pwdn_gpio))
++              gpiod_set_value_cansleep(ov9281->pwdn_gpio, 1);
++
++      /* 8192 cycles prior to first SCCB transaction */
++      delay_us = ov9281_cal_delay(8192);
++      usleep_range(delay_us, delay_us * 2);
++
++      return 0;
++
++disable_clk:
++      clk_disable_unprepare(ov9281->xvclk);
++
++      return ret;
++}
++
++static void __ov9281_power_off(struct ov9281 *ov9281)
++{
++      int ret;
++      struct device *dev = &ov9281->client->dev;
++
++      if (!IS_ERR(ov9281->pwdn_gpio))
++              gpiod_set_value_cansleep(ov9281->pwdn_gpio, 0);
++      clk_disable_unprepare(ov9281->xvclk);
++      if (!IS_ERR(ov9281->reset_gpio))
++              gpiod_set_value_cansleep(ov9281->reset_gpio, 0);
++      if (!IS_ERR_OR_NULL(ov9281->pins_sleep)) {
++              ret = pinctrl_select_state(ov9281->pinctrl,
++                                         ov9281->pins_sleep);
++              if (ret < 0)
++                      dev_dbg(dev, "could not set pins\n");
++      }
++      regulator_bulk_disable(OV9281_NUM_SUPPLIES, ov9281->supplies);
++}
++
++static int ov9281_runtime_resume(struct device *dev)
++{
++      struct i2c_client *client = to_i2c_client(dev);
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct ov9281 *ov9281 = to_ov9281(sd);
++
++      return __ov9281_power_on(ov9281);
++}
++
++static int ov9281_runtime_suspend(struct device *dev)
++{
++      struct i2c_client *client = to_i2c_client(dev);
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct ov9281 *ov9281 = to_ov9281(sd);
++
++      __ov9281_power_off(ov9281);
++
++      return 0;
++}
++
++#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
++static int ov9281_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
++{
++      struct ov9281 *ov9281 = to_ov9281(sd);
++      struct v4l2_mbus_framefmt *try_fmt =
++                              v4l2_subdev_get_try_format(sd, fh->pad, 0);
++      const struct ov9281_mode *def_mode = &supported_modes[0];
++
++      mutex_lock(&ov9281->mutex);
++      /* Initialize try_fmt */
++      try_fmt->width = def_mode->width;
++      try_fmt->height = def_mode->height;
++      try_fmt->code = MEDIA_BUS_FMT_Y10_1X10;
++      try_fmt->field = V4L2_FIELD_NONE;
++
++      mutex_unlock(&ov9281->mutex);
++      /* No crop or compose */
++
++      return 0;
++}
++#endif
++
++static const struct dev_pm_ops ov9281_pm_ops = {
++      SET_RUNTIME_PM_OPS(ov9281_runtime_suspend,
++                         ov9281_runtime_resume, NULL)
++};
++
++#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
++static const struct v4l2_subdev_internal_ops ov9281_internal_ops = {
++      .open = ov9281_open,
++};
++#endif
++
++static const struct v4l2_subdev_core_ops ov9281_core_ops = {
++      .s_power = ov9281_s_power,
++      .ioctl = ov9281_ioctl,
++#ifdef CONFIG_COMPAT
++      .compat_ioctl32 = ov9281_compat_ioctl32,
++#endif
++};
++
++static const struct v4l2_subdev_video_ops ov9281_video_ops = {
++      .s_stream = ov9281_s_stream,
++      .g_frame_interval = OV9281_g_frame_interval,
++};
++
++static const struct v4l2_subdev_pad_ops ov9281_pad_ops = {
++      .enum_mbus_code = ov9281_enum_mbus_code,
++      .enum_frame_size = ov9281_enum_frame_sizes,
++      .get_fmt = ov9281_get_fmt,
++      .set_fmt = ov9281_set_fmt,
++};
++
++static const struct v4l2_subdev_ops ov9281_subdev_ops = {
++      .core   = &ov9281_core_ops,
++      .video  = &ov9281_video_ops,
++      .pad    = &ov9281_pad_ops,
++};
++
++static int ov9281_set_ctrl(struct v4l2_ctrl *ctrl)
++{
++      struct ov9281 *ov9281 = container_of(ctrl->handler,
++                                           struct ov9281, ctrl_handler);
++      struct i2c_client *client = ov9281->client;
++      s64 max;
++      int ret = 0;
++
++      /* Propagate change of current control to all related controls */
++      switch (ctrl->id) {
++      case V4L2_CID_VBLANK:
++              /* Update max exposure while meeting expected vblanking */
++              max = ov9281->cur_mode->height + ctrl->val - 4;
++              __v4l2_ctrl_modify_range(ov9281->exposure,
++                                       ov9281->exposure->minimum, max,
++                                       ov9281->exposure->step,
++                                       ov9281->exposure->default_value);
++              break;
++      }
++
++      if (pm_runtime_get(&client->dev) <= 0)
++              return 0;
++
++      switch (ctrl->id) {
++      case V4L2_CID_EXPOSURE:
++              /* 4 least significant bits of expsoure are fractional part */
++              ret = ov9281_write_reg(ov9281->client, OV9281_REG_EXPOSURE,
++                                     OV9281_REG_VALUE_24BIT, ctrl->val << 4);
++              break;
++      case V4L2_CID_ANALOGUE_GAIN:
++              ret = ov9281_write_reg(ov9281->client, OV9281_REG_GAIN_H,
++                                     OV9281_REG_VALUE_08BIT,
++                                     (ctrl->val >> OV9281_GAIN_H_SHIFT) & OV9281_GAIN_H_MASK);
++              ret |= ov9281_write_reg(ov9281->client, OV9281_REG_GAIN_L,
++                                     OV9281_REG_VALUE_08BIT,
++                                     ctrl->val & OV9281_GAIN_L_MASK);
++              break;
++      case V4L2_CID_VBLANK:
++              ret = ov9281_write_reg(ov9281->client, OV9281_REG_VTS,
++                                     OV9281_REG_VALUE_16BIT,
++                                     ctrl->val + ov9281->cur_mode->height);
++              break;
++      case V4L2_CID_TEST_PATTERN:
++              ret = ov9281_enable_test_pattern(ov9281, ctrl->val);
++              break;
++      default:
++              dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
++                       __func__, ctrl->id, ctrl->val);
++              break;
++      }
++
++      pm_runtime_put(&client->dev);
++
++      return ret;
++}
++
++static const struct v4l2_ctrl_ops ov9281_ctrl_ops = {
++      .s_ctrl = ov9281_set_ctrl,
++};
++
++static int ov9281_initialize_controls(struct ov9281 *ov9281)
++{
++      const struct ov9281_mode *mode;
++      struct v4l2_ctrl_handler *handler;
++      struct v4l2_ctrl *ctrl;
++      s64 exposure_max, vblank_def;
++      u32 h_blank;
++      int ret;
++
++      handler = &ov9281->ctrl_handler;
++      mode = ov9281->cur_mode;
++      ret = v4l2_ctrl_handler_init(handler, 8);
++      if (ret)
++              return ret;
++      handler->lock = &ov9281->mutex;
++
++      ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
++                                    0, 0, link_freq_menu_items);
++      if (ctrl)
++              ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++
++      v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
++                        0, OV9281_PIXEL_RATE, 1, OV9281_PIXEL_RATE);
++
++      h_blank = mode->hts_def - mode->width;
++      ov9281->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
++                              h_blank, h_blank, 1, h_blank);
++      if (ov9281->hblank)
++              ov9281->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++
++      vblank_def = mode->vts_def - mode->height;
++      ov9281->vblank = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
++                              V4L2_CID_VBLANK, vblank_def,
++                              OV9281_VTS_MAX - mode->height,
++                              1, vblank_def);
++
++      exposure_max = mode->vts_def - 4;
++      ov9281->exposure = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
++                              V4L2_CID_EXPOSURE, OV9281_EXPOSURE_MIN,
++                              exposure_max, OV9281_EXPOSURE_STEP,
++                              mode->exp_def);
++
++      ov9281->anal_gain = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
++                              V4L2_CID_ANALOGUE_GAIN, OV9281_GAIN_MIN,
++                              OV9281_GAIN_MAX, OV9281_GAIN_STEP,
++                              OV9281_GAIN_DEFAULT);
++
++      ov9281->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
++                              &ov9281_ctrl_ops, V4L2_CID_TEST_PATTERN,
++                              ARRAY_SIZE(ov9281_test_pattern_menu) - 1,
++                              0, 0, ov9281_test_pattern_menu);
++
++      if (handler->error) {
++              ret = handler->error;
++              dev_err(&ov9281->client->dev,
++                      "Failed to init controls(%d)\n", ret);
++              goto err_free_handler;
++      }
++
++      ov9281->subdev.ctrl_handler = handler;
++
++      return 0;
++
++err_free_handler:
++      v4l2_ctrl_handler_free(handler);
++
++      return ret;
++}
++
++static int ov9281_check_sensor_id(struct ov9281 *ov9281,
++                                struct i2c_client *client)
++{
++      struct device *dev = &ov9281->client->dev;
++      u32 id = 0;
++      int ret;
++
++      ret = ov9281_read_reg(client, OV9281_REG_CHIP_ID,
++                            OV9281_REG_VALUE_16BIT, &id);
++      if (id != CHIP_ID) {
++              dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
++              return -ENODEV;
++      }
++
++      dev_info(dev, "Detected OV%06x sensor\n", CHIP_ID);
++
++      return 0;
++}
++
++static int ov9281_configure_regulators(struct ov9281 *ov9281)
++{
++      unsigned int i;
++
++      for (i = 0; i < OV9281_NUM_SUPPLIES; i++)
++              ov9281->supplies[i].supply = ov9281_supply_names[i];
++
++      return devm_regulator_bulk_get(&ov9281->client->dev,
++                                     OV9281_NUM_SUPPLIES,
++                                     ov9281->supplies);
++}
++
++static int ov9281_probe(struct i2c_client *client,
++                      const struct i2c_device_id *id)
++{
++      struct device *dev = &client->dev;
++      struct device_node *node = dev->of_node;
++      struct ov9281 *ov9281;
++      struct v4l2_subdev *sd;
++      char facing[2];
++      int ret;
++
++      dev_info(dev, "driver version: %02x.%02x.%02x",
++              DRIVER_VERSION >> 16,
++              (DRIVER_VERSION & 0xff00) >> 8,
++              DRIVER_VERSION & 0x00ff);
++
++      ov9281 = devm_kzalloc(dev, sizeof(*ov9281), GFP_KERNEL);
++      if (!ov9281)
++              return -ENOMEM;
++
++      ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
++                                 &ov9281->module_index);
++      ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
++                                     &ov9281->module_facing);
++      ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
++                                     &ov9281->module_name);
++      ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
++                                     &ov9281->len_name);
++      if (ret) {
++              dev_err(dev, "could not get module information!\n");
++              return -EINVAL;
++      }
++
++      ov9281->client = client;
++      ov9281->cur_mode = &supported_modes[0];
++
++      ov9281->xvclk = devm_clk_get(dev, "xvclk");
++      if (IS_ERR(ov9281->xvclk)) {
++              dev_err(dev, "Failed to get xvclk\n");
++              return -EINVAL;
++      }
++      ret = clk_set_rate(ov9281->xvclk, OV9281_XVCLK_FREQ);
++      if (ret < 0) {
++              dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
++              return ret;
++      }
++      if (clk_get_rate(ov9281->xvclk) != OV9281_XVCLK_FREQ)
++              dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
++
++      ov9281->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
++      if (IS_ERR(ov9281->reset_gpio))
++              dev_warn(dev, "Failed to get reset-gpios\n");
++
++      ov9281->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
++      if (IS_ERR(ov9281->pwdn_gpio))
++              dev_warn(dev, "Failed to get pwdn-gpios\n");
++
++      ov9281->pinctrl = devm_pinctrl_get(dev);
++      if (!IS_ERR(ov9281->pinctrl)) {
++              ov9281->pins_default =
++                      pinctrl_lookup_state(ov9281->pinctrl,
++                                           OF_CAMERA_PINCTRL_STATE_DEFAULT);
++              if (IS_ERR(ov9281->pins_default))
++                      dev_err(dev, "could not get default pinstate\n");
++
++              ov9281->pins_sleep =
++                      pinctrl_lookup_state(ov9281->pinctrl,
++                                           OF_CAMERA_PINCTRL_STATE_SLEEP);
++              if (IS_ERR(ov9281->pins_sleep))
++                      dev_err(dev, "could not get sleep pinstate\n");
++      } else {
++              dev_err(dev, "no pinctrl\n");
++      }
++
++      ret = ov9281_configure_regulators(ov9281);
++      if (ret) {
++              dev_err(dev, "Failed to get power regulators\n");
++              return ret;
++      }
++
++      mutex_init(&ov9281->mutex);
++
++      sd = &ov9281->subdev;
++      v4l2_i2c_subdev_init(sd, client, &ov9281_subdev_ops);
++      ret = ov9281_initialize_controls(ov9281);
++      if (ret)
++              goto err_destroy_mutex;
++
++      ret = __ov9281_power_on(ov9281);
++      if (ret)
++              goto err_free_handler;
++
++      ret = ov9281_check_sensor_id(ov9281, client);
++      if (ret)
++              goto err_power_off;
++
++#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
++      sd->internal_ops = &ov9281_internal_ops;
++      sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
++#endif
++#if defined(CONFIG_MEDIA_CONTROLLER)
++      ov9281->pad.flags = MEDIA_PAD_FL_SOURCE;
++      sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
++      ret = media_entity_init(&sd->entity, 1, &ov9281->pad, 0);
++      if (ret < 0)
++              goto err_power_off;
++#endif
++
++      memset(facing, 0, sizeof(facing));
++      if (strcmp(ov9281->module_facing, "back") == 0)
++              facing[0] = 'b';
++      else
++              facing[0] = 'f';
++
++      snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
++               ov9281->module_index, facing,
++               OV9281_NAME, dev_name(sd->dev));
++      ret = v4l2_async_register_subdev_sensor_common(sd);
++      if (ret) {
++              dev_err(dev, "v4l2 async register subdev failed\n");
++              goto err_clean_entity;
++      }
++
++      pm_runtime_set_active(dev);
++      pm_runtime_enable(dev);
++      pm_runtime_idle(dev);
++
++      return 0;
++
++err_clean_entity:
++#if defined(CONFIG_MEDIA_CONTROLLER)
++      media_entity_cleanup(&sd->entity);
++#endif
++err_power_off:
++      __ov9281_power_off(ov9281);
++err_free_handler:
++      v4l2_ctrl_handler_free(&ov9281->ctrl_handler);
++err_destroy_mutex:
++      mutex_destroy(&ov9281->mutex);
++
++      return ret;
++}
++
++static int ov9281_remove(struct i2c_client *client)
++{
++      struct v4l2_subdev *sd = i2c_get_clientdata(client);
++      struct ov9281 *ov9281 = to_ov9281(sd);
++
++      v4l2_async_unregister_subdev(sd);
++#if defined(CONFIG_MEDIA_CONTROLLER)
++      media_entity_cleanup(&sd->entity);
++#endif
++      v4l2_ctrl_handler_free(&ov9281->ctrl_handler);
++      mutex_destroy(&ov9281->mutex);
++
++      pm_runtime_disable(&client->dev);
++      if (!pm_runtime_status_suspended(&client->dev))
++              __ov9281_power_off(ov9281);
++      pm_runtime_set_suspended(&client->dev);
++
++      return 0;
++}
++
++#if IS_ENABLED(CONFIG_OF)
++static const struct of_device_id ov9281_of_match[] = {
++      { .compatible = "ovti,ov9281" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, ov9281_of_match);
++#endif
++
++static const struct i2c_device_id ov9281_match_id[] = {
++      { "ovti,ov9281", 0 },
++      { },
++};
++
++static struct i2c_driver ov9281_i2c_driver = {
++      .driver = {
++              .name = OV9281_NAME,
++              .pm = &ov9281_pm_ops,
++              .of_match_table = of_match_ptr(ov9281_of_match),
++      },
++      .probe          = &ov9281_probe,
++      .remove         = &ov9281_remove,
++      .id_table       = ov9281_match_id,
++};
++
++static int __init sensor_mod_init(void)
++{
++      return i2c_add_driver(&ov9281_i2c_driver);
++}
++
++static void __exit sensor_mod_exit(void)
++{
++      i2c_del_driver(&ov9281_i2c_driver);
++}
++
++device_initcall_sync(sensor_mod_init);
++module_exit(sensor_mod_exit);
++
++MODULE_DESCRIPTION("OmniVision ov9281 sensor driver");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0871-media-i2c-ov9281-fix-mclk-issue-when-probe-multiple-.patch b/target/linux/bcm27xx/patches-5.4/950-0871-media-i2c-ov9281-fix-mclk-issue-when-probe-multiple-.patch
new file mode 100644 (file)
index 0000000..4a2bbed
--- /dev/null
@@ -0,0 +1,60 @@
+From a02d918e1bf4dc70c51b630c12182e038d0a73d2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 14 Apr 2020 15:47:09 +0100
+Subject: [PATCH] media: i2c: ov9281: fix mclk issue when probe
+ multiple camera.
+
+Takes the ov9281 part only from the Rockchip's patch.
+
+Change-Id: I30e833baf2c1bb07d6d87ddb3b00759ab45a90e4
+Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
+---
+ drivers/media/i2c/ov9281.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/media/i2c/ov9281.c
++++ b/drivers/media/i2c/ov9281.c
+@@ -3,6 +3,7 @@
+  * ov9281 driver
+  *
+  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
++ * V0.0X01.0X02 fix mclk issue when probe multiple camera.
+  */
+ #include <linux/clk.h>
+@@ -22,7 +23,7 @@
+ #include <media/v4l2-subdev.h>
+ #include <linux/pinctrl/consumer.h>
+-#define DRIVER_VERSION                        KERNEL_VERSION(0, 0x01, 0x0)
++#define DRIVER_VERSION                        KERNEL_VERSION(0, 0x01, 0x2)
+ #ifndef V4L2_CID_DIGITAL_GAIN
+ #define V4L2_CID_DIGITAL_GAIN         V4L2_CID_GAIN
+@@ -676,6 +677,12 @@ static int __ov9281_power_on(struct ov92
+                       dev_err(dev, "could not set pins\n");
+       }
++      ret = clk_set_rate(ov9281->xvclk, OV9281_XVCLK_FREQ);
++      if (ret < 0)
++              dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
++      if (clk_get_rate(ov9281->xvclk) != OV9281_XVCLK_FREQ)
++              dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
++
+       ret = clk_prepare_enable(ov9281->xvclk);
+       if (ret < 0) {
+               dev_err(dev, "Failed to enable xvclk\n");
+@@ -1008,13 +1015,6 @@ static int ov9281_probe(struct i2c_clien
+               dev_err(dev, "Failed to get xvclk\n");
+               return -EINVAL;
+       }
+-      ret = clk_set_rate(ov9281->xvclk, OV9281_XVCLK_FREQ);
+-      if (ret < 0) {
+-              dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
+-              return ret;
+-      }
+-      if (clk_get_rate(ov9281->xvclk) != OV9281_XVCLK_FREQ)
+-              dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
+       ov9281->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(ov9281->reset_gpio))
diff --git a/target/linux/bcm27xx/patches-5.4/950-0872-media-i2c-ov9281-add-enum_frame_interval-function-fo.patch b/target/linux/bcm27xx/patches-5.4/950-0872-media-i2c-ov9281-add-enum_frame_interval-function-fo.patch
new file mode 100644 (file)
index 0000000..c772521
--- /dev/null
@@ -0,0 +1,97 @@
+From c99b6817190eefc77c91567e57fc930656f205bf Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 14 Apr 2020 15:51:50 +0100
+Subject: [PATCH] media: i2c: ov9281: add enum_frame_interval
+ function for iq tool 2.2 and hal3
+
+Adds the ov9281 parts of the Rockchip patch adding enum_frame_interval to
+a large number of drivers.
+
+Change-Id: I03344cd6cf278dd7c18fce8e97479089ef185a5c
+Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
+---
+ drivers/media/i2c/ov9281.c | 31 ++++++++++++++++++++++++++-----
+ 1 file changed, 26 insertions(+), 5 deletions(-)
+
+--- a/drivers/media/i2c/ov9281.c
++++ b/drivers/media/i2c/ov9281.c
+@@ -4,6 +4,7 @@
+  *
+  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+  * V0.0X01.0X02 fix mclk issue when probe multiple camera.
++ * V0.0X01.0X03 add enum_frame_interval function.
+  */
+ #include <linux/clk.h>
+@@ -23,7 +24,7 @@
+ #include <media/v4l2-subdev.h>
+ #include <linux/pinctrl/consumer.h>
+-#define DRIVER_VERSION                        KERNEL_VERSION(0, 0x01, 0x2)
++#define DRIVER_VERSION                        KERNEL_VERSION(0, 0x01, 0x3)
+ #ifndef V4L2_CID_DIGITAL_GAIN
+ #define V4L2_CID_DIGITAL_GAIN         V4L2_CID_GAIN
+@@ -92,7 +93,7 @@ struct regval {
+ struct ov9281_mode {
+       u32 width;
+       u32 height;
+-      u32 max_fps;
++      struct v4l2_fract max_fps;
+       u32 hts_def;
+       u32 vts_def;
+       u32 exp_def;
+@@ -246,7 +247,10 @@ static const struct ov9281_mode supporte
+       {
+               .width = 1280,
+               .height = 800,
+-              .max_fps = 120,
++              .max_fps = {
++                      .numerator = 10000,
++                      .denominator = 1200000,
++              },
+               .exp_def = 0x0320,
+               .hts_def = 0x0b60,//0x2d8*4
+               .vts_def = 0x038e,
+@@ -483,8 +487,7 @@ static int OV9281_g_frame_interval(struc
+       const struct ov9281_mode *mode = ov9281->cur_mode;
+       mutex_lock(&ov9281->mutex);
+-      fi->interval.numerator = 10000;
+-      fi->interval.denominator = mode->max_fps * 10000;
++      fi->interval = mode->max_fps;
+       mutex_unlock(&ov9281->mutex);
+       return 0;
+@@ -778,6 +781,23 @@ static int ov9281_open(struct v4l2_subde
+ }
+ #endif
++static int
++ov9281_enum_frame_interval(struct v4l2_subdev *sd,
++                         struct v4l2_subdev_pad_config *cfg,
++                         struct v4l2_subdev_frame_interval_enum *fie)
++{
++      if (fie->index >= ARRAY_SIZE(supported_modes))
++              return -EINVAL;
++
++      if (fie->code != MEDIA_BUS_FMT_Y10_1X10)
++              return -EINVAL;
++
++      fie->width = supported_modes[fie->index].width;
++      fie->height = supported_modes[fie->index].height;
++      fie->interval = supported_modes[fie->index].max_fps;
++      return 0;
++}
++
+ static const struct dev_pm_ops ov9281_pm_ops = {
+       SET_RUNTIME_PM_OPS(ov9281_runtime_suspend,
+                          ov9281_runtime_resume, NULL)
+@@ -805,6 +825,7 @@ static const struct v4l2_subdev_video_op
+ static const struct v4l2_subdev_pad_ops ov9281_pad_ops = {
+       .enum_mbus_code = ov9281_enum_mbus_code,
+       .enum_frame_size = ov9281_enum_frame_sizes,
++      .enum_frame_interval = ov9281_enum_frame_interval,
+       .get_fmt = ov9281_get_fmt,
+       .set_fmt = ov9281_set_fmt,
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0873-media-i2c-ov9281-Fixup-for-recent-kernel-releases-an.patch b/target/linux/bcm27xx/patches-5.4/950-0873-media-i2c-ov9281-Fixup-for-recent-kernel-releases-an.patch
new file mode 100644 (file)
index 0000000..4f3bcf3
--- /dev/null
@@ -0,0 +1,693 @@
+From 898198428aa35f52c2b58c037e960dcbcc4ef9d8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 14 Apr 2020 16:12:33 +0100
+Subject: [PATCH] media: i2c: ov9281: Fixup for recent kernel
+ releases, and remove custom code
+
+The Rockchip driver was based on a 4.4 kernel, and had several custom
+Rockchip parts.
+
+Update to 5.4 kernel APIs, with the relevant controls required by
+libcamera, and remove custom Rockchip parts.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/Kconfig  |   2 +-
+ drivers/media/i2c/ov9281.c | 361 +++++++++++++------------------------
+ 2 files changed, 123 insertions(+), 240 deletions(-)
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -857,7 +857,7 @@ config VIDEO_OV9640
+ config VIDEO_OV9281
+       tristate "OmniVision OV9281 sensor support"
+-      depends on I2C && VIDEO_V4L2
++      depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       help
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+--- a/drivers/media/i2c/ov9281.c
++++ b/drivers/media/i2c/ov9281.c
+@@ -1,6 +1,11 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * ov9281 driver
++ * Omnivision OV9281 1280x800 global shutter image sensor driver
++ *
++ * This driver has been taken from
++ * https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/media/i2c/ov9281.c
++ * cleaned up, made to compile against mainline kernels instead of the Rockchip
++ * vendor kernel, and the relevant controls added to work with libcamera.
+  *
+  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+  * V0.0X01.0X02 fix mclk issue when probe multiple camera.
+@@ -17,22 +22,18 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/sysfs.h>
+ #include <linux/slab.h>
+-#include <linux/rk-camera-module.h>
+ #include <media/media-entity.h>
+ #include <media/v4l2-async.h>
+ #include <media/v4l2-ctrls.h>
+ #include <media/v4l2-subdev.h>
+-#include <linux/pinctrl/consumer.h>
+-
+-#define DRIVER_VERSION                        KERNEL_VERSION(0, 0x01, 0x3)
+-
+-#ifndef V4L2_CID_DIGITAL_GAIN
+-#define V4L2_CID_DIGITAL_GAIN         V4L2_CID_GAIN
+-#endif
+ #define OV9281_LINK_FREQ_400MHZ               400000000
++#define OV9281_LANES                  2
++#define OV9281_BITS_PER_SAMPLE                10
++
+ /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
+-#define OV9281_PIXEL_RATE             (OV9281_LINK_FREQ_400MHZ * 2 * 2 / 10)
++#define OV9281_PIXEL_RATE             (OV9281_LINK_FREQ_400MHZ * 2 * \
++                                       OV9281_LANES / OV9281_BITS_PER_SAMPLE)
+ #define OV9281_XVCLK_FREQ             24000000
+ #define CHIP_ID                               0x9281
+@@ -63,18 +64,24 @@
+ #define OV9281_REG_VTS                        0x380e
++/*
++ * OV9281 native and active pixel array size.
++ * Datasheet not available to confirm these values, so assume there are no
++ * border pixels.
++ */
++#define OV9281_NATIVE_WIDTH           1280U
++#define OV9281_NATIVE_HEIGHT          800U
++#define OV9281_PIXEL_ARRAY_LEFT               0U
++#define OV9281_PIXEL_ARRAY_TOP                0U
++#define OV9281_PIXEL_ARRAY_WIDTH      1280U
++#define OV9281_PIXEL_ARRAY_HEIGHT     800U
++
+ #define REG_NULL                      0xFFFF
+ #define OV9281_REG_VALUE_08BIT                1
+ #define OV9281_REG_VALUE_16BIT                2
+ #define OV9281_REG_VALUE_24BIT                3
+-#define OV9281_LANES                  2
+-#define OV9281_BITS_PER_SAMPLE                10
+-
+-#define OF_CAMERA_PINCTRL_STATE_DEFAULT       "rockchip,camera_default"
+-#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
+-
+ #define OV9281_NAME                   "ov9281"
+ static const char * const ov9281_supply_names[] = {
+@@ -93,10 +100,10 @@ struct regval {
+ struct ov9281_mode {
+       u32 width;
+       u32 height;
+-      struct v4l2_fract max_fps;
+       u32 hts_def;
+       u32 vts_def;
+       u32 exp_def;
++      struct v4l2_rect crop;
+       const struct regval *reg_list;
+ };
+@@ -107,10 +114,6 @@ struct ov9281 {
+       struct gpio_desc        *pwdn_gpio;
+       struct regulator_bulk_data supplies[OV9281_NUM_SUPPLIES];
+-      struct pinctrl          *pinctrl;
+-      struct pinctrl_state    *pins_default;
+-      struct pinctrl_state    *pins_sleep;
+-
+       struct v4l2_subdev      subdev;
+       struct media_pad        pad;
+       struct v4l2_ctrl_handler ctrl_handler;
+@@ -124,23 +127,12 @@ struct ov9281 {
+       bool                    streaming;
+       bool                    power_on;
+       const struct ov9281_mode *cur_mode;
+-      u32                     module_index;
+-      const char              *module_facing;
+-      const char              *module_name;
+-      const char              *len_name;
+ };
+ #define to_ov9281(sd) container_of(sd, struct ov9281, subdev)
+ /*
+  * Xclk 24Mhz
+- */
+-static const struct regval ov9281_global_regs[] = {
+-      {REG_NULL, 0x00},
+-};
+-
+-/*
+- * Xclk 24Mhz
+  * max_framerate 120fps
+  * mipi_datarate per lane 800Mbps
+  */
+@@ -247,13 +239,15 @@ static const struct ov9281_mode supporte
+       {
+               .width = 1280,
+               .height = 800,
+-              .max_fps = {
+-                      .numerator = 10000,
+-                      .denominator = 1200000,
+-              },
+               .exp_def = 0x0320,
+-              .hts_def = 0x0b60,//0x2d8*4
++              .hts_def = 0x05b0,      /* 0x2d8*2 */
+               .vts_def = 0x038e,
++              .crop = {
++                      .left = 0,
++                      .top = 0,
++                      .width = 1280,
++                      .height = 800
++              },
+               .reg_list = ov9281_1280x800_regs,
+       },
+ };
+@@ -389,22 +383,28 @@ static int ov9281_set_fmt(struct v4l2_su
+       fmt->format.width = mode->width;
+       fmt->format.height = mode->height;
+       fmt->format.field = V4L2_FIELD_NONE;
++      fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
++      fmt->format.ycbcr_enc =
++                      V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
++      fmt->format.quantization =
++              V4L2_MAP_QUANTIZATION_DEFAULT(true, fmt->format.colorspace,
++                                            fmt->format.ycbcr_enc);
++      fmt->format.xfer_func =
++              V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
++
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+               *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
+-#else
+-              mutex_unlock(&ov9281->mutex);
+-              return -ENOTTY;
+-#endif
+       } else {
+               ov9281->cur_mode = mode;
+               h_blank = mode->hts_def - mode->width;
+               __v4l2_ctrl_modify_range(ov9281->hblank, h_blank,
+                                        h_blank, 1, h_blank);
++              __v4l2_ctrl_s_ctrl(ov9281->hblank, h_blank);
+               vblank_def = mode->vts_def - mode->height;
+               __v4l2_ctrl_modify_range(ov9281->vblank, vblank_def,
+                                        OV9281_VTS_MAX - mode->height,
+                                        1, vblank_def);
++              __v4l2_ctrl_s_ctrl(ov9281->vblank, vblank_def);
+       }
+       mutex_unlock(&ov9281->mutex);
+@@ -421,17 +421,21 @@ static int ov9281_get_fmt(struct v4l2_su
+       mutex_lock(&ov9281->mutex);
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+               fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+-#else
+-              mutex_unlock(&ov9281->mutex);
+-              return -ENOTTY;
+-#endif
+       } else {
+               fmt->format.width = mode->width;
+               fmt->format.height = mode->height;
+               fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
+               fmt->format.field = V4L2_FIELD_NONE;
++              fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
++              fmt->format.ycbcr_enc =
++                      V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
++              fmt->format.quantization =
++                      V4L2_MAP_QUANTIZATION_DEFAULT(true,
++                                                    fmt->format.colorspace,
++                                                    fmt->format.ycbcr_enc);
++              fmt->format.xfer_func =
++                      V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
+       }
+       mutex_unlock(&ov9281->mutex);
+@@ -442,7 +446,7 @@ static int ov9281_enum_mbus_code(struct
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_mbus_code_enum *code)
+ {
+-      if (code->index != 0)
++      if (code->index)
+               return -EINVAL;
+       code->code = MEDIA_BUS_FMT_Y10_1X10;
+@@ -480,88 +484,56 @@ static int ov9281_enable_test_pattern(st
+                               OV9281_REG_VALUE_08BIT, val);
+ }
+-static int OV9281_g_frame_interval(struct v4l2_subdev *sd,
+-                                 struct v4l2_subdev_frame_interval *fi)
+-{
+-      struct ov9281 *ov9281 = to_ov9281(sd);
+-      const struct ov9281_mode *mode = ov9281->cur_mode;
+-
+-      mutex_lock(&ov9281->mutex);
+-      fi->interval = mode->max_fps;
+-      mutex_unlock(&ov9281->mutex);
++static const struct v4l2_rect *
++__ov9281_get_pad_crop(struct ov9281 *ov9281, struct v4l2_subdev_pad_config *cfg,
++                    unsigned int pad, enum v4l2_subdev_format_whence which)
++{
++      switch (which) {
++      case V4L2_SUBDEV_FORMAT_TRY:
++              return v4l2_subdev_get_try_crop(&ov9281->subdev, cfg, pad);
++      case V4L2_SUBDEV_FORMAT_ACTIVE:
++              return &ov9281->cur_mode->crop;
++      }
+-      return 0;
++      return NULL;
+ }
+-static void ov9281_get_module_inf(struct ov9281 *ov9281,
+-                                struct rkmodule_inf *inf)
++static int ov9281_get_selection(struct v4l2_subdev *sd,
++                              struct v4l2_subdev_pad_config *cfg,
++                              struct v4l2_subdev_selection *sel)
+ {
+-      memset(inf, 0, sizeof(*inf));
+-      strlcpy(inf->base.sensor, OV9281_NAME, sizeof(inf->base.sensor));
+-      strlcpy(inf->base.module, ov9281->module_name,
+-              sizeof(inf->base.module));
+-      strlcpy(inf->base.lens, ov9281->len_name, sizeof(inf->base.lens));
+-}
++      switch (sel->target) {
++      case V4L2_SEL_TGT_CROP: {
++              struct ov9281 *ov9281 = to_ov9281(sd);
+-static long ov9281_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+-{
+-      struct ov9281 *ov9281 = to_ov9281(sd);
+-      long ret = 0;
++              mutex_lock(&ov9281->mutex);
++              sel->r = *__ov9281_get_pad_crop(ov9281, cfg, sel->pad,
++                                              sel->which);
++              mutex_unlock(&ov9281->mutex);
+-      switch (cmd) {
+-      case RKMODULE_GET_MODULE_INFO:
+-              ov9281_get_module_inf(ov9281, (struct rkmodule_inf *)arg);
+-              break;
+-      default:
+-              ret = -ENOIOCTLCMD;
+-              break;
++              return 0;
+       }
+-      return ret;
+-}
++      case V4L2_SEL_TGT_NATIVE_SIZE:
++              sel->r.top = 0;
++              sel->r.left = 0;
++              sel->r.width = OV9281_NATIVE_WIDTH;
++              sel->r.height = OV9281_NATIVE_HEIGHT;
+-#ifdef CONFIG_COMPAT
+-static long ov9281_compat_ioctl32(struct v4l2_subdev *sd,
+-                                unsigned int cmd, unsigned long arg)
+-{
+-      void __user *up = compat_ptr(arg);
+-      struct rkmodule_inf *inf;
+-      struct rkmodule_awb_cfg *cfg;
+-      long ret;
+-
+-      switch (cmd) {
+-      case RKMODULE_GET_MODULE_INFO:
+-              inf = kzalloc(sizeof(*inf), GFP_KERNEL);
+-              if (!inf) {
+-                      ret = -ENOMEM;
+-                      return ret;
+-              }
++              return 0;
+-              ret = ov9281_ioctl(sd, cmd, inf);
+-              if (!ret)
+-                      ret = copy_to_user(up, inf, sizeof(*inf));
+-              kfree(inf);
+-              break;
+-      case RKMODULE_AWB_CFG:
+-              cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+-              if (!cfg) {
+-                      ret = -ENOMEM;
+-                      return ret;
+-              }
++      case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
++              sel->r.top = OV9281_PIXEL_ARRAY_TOP;
++              sel->r.left = OV9281_PIXEL_ARRAY_LEFT;
++              sel->r.width = OV9281_PIXEL_ARRAY_WIDTH;
++              sel->r.height = OV9281_PIXEL_ARRAY_HEIGHT;
+-              ret = copy_from_user(cfg, up, sizeof(*cfg));
+-              if (!ret)
+-                      ret = ov9281_ioctl(sd, cmd, cfg);
+-              kfree(cfg);
+-              break;
+-      default:
+-              ret = -ENOIOCTLCMD;
+-              break;
++              return 0;
+       }
+-      return ret;
++      return -EINVAL;
+ }
+-#endif
+ static int __ov9281_start_stream(struct ov9281 *ov9281)
+ {
+@@ -643,12 +615,6 @@ static int ov9281_s_power(struct v4l2_su
+                       pm_runtime_put_noidle(&client->dev);
+                       goto unlock_and_return;
+               }
+-              ret = ov9281_write_array(ov9281->client, ov9281_global_regs);
+-              if (ret) {
+-                      v4l2_err(sd, "could not set init registers\n");
+-                      pm_runtime_put_noidle(&client->dev);
+-                      goto unlock_and_return;
+-              }
+               ov9281->power_on = true;
+       } else {
+               pm_runtime_put(&client->dev);
+@@ -673,18 +639,12 @@ static int __ov9281_power_on(struct ov92
+       u32 delay_us;
+       struct device *dev = &ov9281->client->dev;
+-      if (!IS_ERR_OR_NULL(ov9281->pins_default)) {
+-              ret = pinctrl_select_state(ov9281->pinctrl,
+-                                         ov9281->pins_default);
+-              if (ret < 0)
+-                      dev_err(dev, "could not set pins\n");
+-      }
+-
+       ret = clk_set_rate(ov9281->xvclk, OV9281_XVCLK_FREQ);
+       if (ret < 0)
+               dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
+       if (clk_get_rate(ov9281->xvclk) != OV9281_XVCLK_FREQ)
+-              dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
++              dev_warn(dev, "xvclk mismatched, modes are based on 24MHz - rate is %lu\n",
++                       clk_get_rate(ov9281->xvclk));
+       ret = clk_prepare_enable(ov9281->xvclk);
+       if (ret < 0) {
+@@ -722,20 +682,11 @@ disable_clk:
+ static void __ov9281_power_off(struct ov9281 *ov9281)
+ {
+-      int ret;
+-      struct device *dev = &ov9281->client->dev;
+-
+       if (!IS_ERR(ov9281->pwdn_gpio))
+               gpiod_set_value_cansleep(ov9281->pwdn_gpio, 0);
+       clk_disable_unprepare(ov9281->xvclk);
+       if (!IS_ERR(ov9281->reset_gpio))
+               gpiod_set_value_cansleep(ov9281->reset_gpio, 0);
+-      if (!IS_ERR_OR_NULL(ov9281->pins_sleep)) {
+-              ret = pinctrl_select_state(ov9281->pinctrl,
+-                                         ov9281->pins_sleep);
+-              if (ret < 0)
+-                      dev_dbg(dev, "could not set pins\n");
+-      }
+       regulator_bulk_disable(OV9281_NUM_SUPPLIES, ov9281->supplies);
+ }
+@@ -759,7 +710,6 @@ static int ov9281_runtime_suspend(struct
+       return 0;
+ }
+-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ static int ov9281_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+ {
+       struct ov9281 *ov9281 = to_ov9281(sd);
+@@ -773,61 +723,42 @@ static int ov9281_open(struct v4l2_subde
+       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->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(try_fmt->colorspace);
++      try_fmt->quantization =
++              V4L2_MAP_QUANTIZATION_DEFAULT(true, try_fmt->colorspace,
++                                            try_fmt->ycbcr_enc);
++      try_fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(try_fmt->colorspace);
+       mutex_unlock(&ov9281->mutex);
+       /* No crop or compose */
+       return 0;
+ }
+-#endif
+-
+-static int
+-ov9281_enum_frame_interval(struct v4l2_subdev *sd,
+-                         struct v4l2_subdev_pad_config *cfg,
+-                         struct v4l2_subdev_frame_interval_enum *fie)
+-{
+-      if (fie->index >= ARRAY_SIZE(supported_modes))
+-              return -EINVAL;
+-
+-      if (fie->code != MEDIA_BUS_FMT_Y10_1X10)
+-              return -EINVAL;
+-
+-      fie->width = supported_modes[fie->index].width;
+-      fie->height = supported_modes[fie->index].height;
+-      fie->interval = supported_modes[fie->index].max_fps;
+-      return 0;
+-}
+ static const struct dev_pm_ops ov9281_pm_ops = {
+       SET_RUNTIME_PM_OPS(ov9281_runtime_suspend,
+                          ov9281_runtime_resume, NULL)
+ };
+-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+ static const struct v4l2_subdev_internal_ops ov9281_internal_ops = {
+       .open = ov9281_open,
+ };
+-#endif
+ static const struct v4l2_subdev_core_ops ov9281_core_ops = {
+       .s_power = ov9281_s_power,
+-      .ioctl = ov9281_ioctl,
+-#ifdef CONFIG_COMPAT
+-      .compat_ioctl32 = ov9281_compat_ioctl32,
+-#endif
+ };
+ static const struct v4l2_subdev_video_ops ov9281_video_ops = {
+       .s_stream = ov9281_s_stream,
+-      .g_frame_interval = OV9281_g_frame_interval,
+ };
+ static const struct v4l2_subdev_pad_ops ov9281_pad_ops = {
+       .enum_mbus_code = ov9281_enum_mbus_code,
+       .enum_frame_size = ov9281_enum_frame_sizes,
+-      .enum_frame_interval = ov9281_enum_frame_interval,
+       .get_fmt = ov9281_get_fmt,
+       .set_fmt = ov9281_set_fmt,
++      .get_selection = ov9281_get_selection,
+ };
+ static const struct v4l2_subdev_ops ov9281_subdev_ops = {
+@@ -868,7 +799,8 @@ static int ov9281_set_ctrl(struct v4l2_c
+       case V4L2_CID_ANALOGUE_GAIN:
+               ret = ov9281_write_reg(ov9281->client, OV9281_REG_GAIN_H,
+                                      OV9281_REG_VALUE_08BIT,
+-                                     (ctrl->val >> OV9281_GAIN_H_SHIFT) & OV9281_GAIN_H_MASK);
++                                     (ctrl->val >> OV9281_GAIN_H_SHIFT) &
++                                                      OV9281_GAIN_H_MASK);
+               ret |= ov9281_write_reg(ov9281->client, OV9281_REG_GAIN_L,
+                                      OV9281_REG_VALUE_08BIT,
+                                      ctrl->val & OV9281_GAIN_L_MASK);
+@@ -922,31 +854,34 @@ static int ov9281_initialize_controls(st
+       h_blank = mode->hts_def - mode->width;
+       ov9281->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
+-                              h_blank, h_blank, 1, h_blank);
++                                         h_blank, h_blank, 1, h_blank);
+       if (ov9281->hblank)
+               ov9281->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+       vblank_def = mode->vts_def - mode->height;
+       ov9281->vblank = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
+-                              V4L2_CID_VBLANK, vblank_def,
+-                              OV9281_VTS_MAX - mode->height,
+-                              1, vblank_def);
++                                         V4L2_CID_VBLANK, vblank_def,
++                                         OV9281_VTS_MAX - mode->height, 1,
++                                         vblank_def);
+       exposure_max = mode->vts_def - 4;
+       ov9281->exposure = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
+-                              V4L2_CID_EXPOSURE, OV9281_EXPOSURE_MIN,
+-                              exposure_max, OV9281_EXPOSURE_STEP,
+-                              mode->exp_def);
++                                           V4L2_CID_EXPOSURE,
++                                           OV9281_EXPOSURE_MIN, exposure_max,
++                                           OV9281_EXPOSURE_STEP,
++                                           mode->exp_def);
+       ov9281->anal_gain = v4l2_ctrl_new_std(handler, &ov9281_ctrl_ops,
+-                              V4L2_CID_ANALOGUE_GAIN, OV9281_GAIN_MIN,
+-                              OV9281_GAIN_MAX, OV9281_GAIN_STEP,
+-                              OV9281_GAIN_DEFAULT);
+-
+-      ov9281->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
+-                              &ov9281_ctrl_ops, V4L2_CID_TEST_PATTERN,
+-                              ARRAY_SIZE(ov9281_test_pattern_menu) - 1,
+-                              0, 0, ov9281_test_pattern_menu);
++                                            V4L2_CID_ANALOGUE_GAIN,
++                                            OV9281_GAIN_MIN, OV9281_GAIN_MAX,
++                                            OV9281_GAIN_STEP,
++                                            OV9281_GAIN_DEFAULT);
++
++      ov9281->test_pattern =
++              v4l2_ctrl_new_std_menu_items(handler, &ov9281_ctrl_ops,
++                                           V4L2_CID_TEST_PATTERN,
++                                           ARRAY_SIZE(ov9281_test_pattern_menu) - 1,
++                                           0, 0, ov9281_test_pattern_menu);
+       if (handler->error) {
+               ret = handler->error;
+@@ -1000,34 +935,14 @@ static int ov9281_probe(struct i2c_clien
+                       const struct i2c_device_id *id)
+ {
+       struct device *dev = &client->dev;
+-      struct device_node *node = dev->of_node;
+       struct ov9281 *ov9281;
+       struct v4l2_subdev *sd;
+-      char facing[2];
+       int ret;
+-      dev_info(dev, "driver version: %02x.%02x.%02x",
+-              DRIVER_VERSION >> 16,
+-              (DRIVER_VERSION & 0xff00) >> 8,
+-              DRIVER_VERSION & 0x00ff);
+-
+       ov9281 = devm_kzalloc(dev, sizeof(*ov9281), GFP_KERNEL);
+       if (!ov9281)
+               return -ENOMEM;
+-      ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
+-                                 &ov9281->module_index);
+-      ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
+-                                     &ov9281->module_facing);
+-      ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
+-                                     &ov9281->module_name);
+-      ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
+-                                     &ov9281->len_name);
+-      if (ret) {
+-              dev_err(dev, "could not get module information!\n");
+-              return -EINVAL;
+-      }
+-
+       ov9281->client = client;
+       ov9281->cur_mode = &supported_modes[0];
+@@ -1037,31 +952,15 @@ static int ov9281_probe(struct i2c_clien
+               return -EINVAL;
+       }
+-      ov9281->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
++      ov9281->reset_gpio = devm_gpiod_get_optional(dev, "reset",
++                                                   GPIOD_OUT_LOW);
+       if (IS_ERR(ov9281->reset_gpio))
+               dev_warn(dev, "Failed to get reset-gpios\n");
+-      ov9281->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
++      ov9281->pwdn_gpio = devm_gpiod_get_optional(dev, "pwdn", GPIOD_OUT_LOW);
+       if (IS_ERR(ov9281->pwdn_gpio))
+               dev_warn(dev, "Failed to get pwdn-gpios\n");
+-      ov9281->pinctrl = devm_pinctrl_get(dev);
+-      if (!IS_ERR(ov9281->pinctrl)) {
+-              ov9281->pins_default =
+-                      pinctrl_lookup_state(ov9281->pinctrl,
+-                                           OF_CAMERA_PINCTRL_STATE_DEFAULT);
+-              if (IS_ERR(ov9281->pins_default))
+-                      dev_err(dev, "could not get default pinstate\n");
+-
+-              ov9281->pins_sleep =
+-                      pinctrl_lookup_state(ov9281->pinctrl,
+-                                           OF_CAMERA_PINCTRL_STATE_SLEEP);
+-              if (IS_ERR(ov9281->pins_sleep))
+-                      dev_err(dev, "could not get sleep pinstate\n");
+-      } else {
+-              dev_err(dev, "no pinctrl\n");
+-      }
+-
+       ret = ov9281_configure_regulators(ov9281);
+       if (ret) {
+               dev_err(dev, "Failed to get power regulators\n");
+@@ -1084,26 +983,16 @@ static int ov9281_probe(struct i2c_clien
+       if (ret)
+               goto err_power_off;
+-#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+       sd->internal_ops = &ov9281_internal_ops;
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+-#endif
+-#if defined(CONFIG_MEDIA_CONTROLLER)
++
+       ov9281->pad.flags = MEDIA_PAD_FL_SOURCE;
+-      sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+-      ret = media_entity_init(&sd->entity, 1, &ov9281->pad, 0);
++      sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
++      ret = media_entity_pads_init(&sd->entity, 1, &ov9281->pad);
+       if (ret < 0)
+               goto err_power_off;
+-#endif
+-
+-      memset(facing, 0, sizeof(facing));
+-      if (strcmp(ov9281->module_facing, "back") == 0)
+-              facing[0] = 'b';
+-      else
+-              facing[0] = 'f';
+-      snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
+-               ov9281->module_index, facing,
++      snprintf(sd->name, sizeof(sd->name), "m%s %s",
+                OV9281_NAME, dev_name(sd->dev));
+       ret = v4l2_async_register_subdev_sensor_common(sd);
+       if (ret) {
+@@ -1118,9 +1007,7 @@ static int ov9281_probe(struct i2c_clien
+       return 0;
+ err_clean_entity:
+-#if defined(CONFIG_MEDIA_CONTROLLER)
+       media_entity_cleanup(&sd->entity);
+-#endif
+ err_power_off:
+       __ov9281_power_off(ov9281);
+ err_free_handler:
+@@ -1137,9 +1024,7 @@ static int ov9281_remove(struct i2c_clie
+       struct ov9281 *ov9281 = to_ov9281(sd);
+       v4l2_async_unregister_subdev(sd);
+-#if defined(CONFIG_MEDIA_CONTROLLER)
+       media_entity_cleanup(&sd->entity);
+-#endif
+       v4l2_ctrl_handler_free(&ov9281->ctrl_handler);
+       mutex_destroy(&ov9281->mutex);
+@@ -1151,13 +1036,11 @@ static int ov9281_remove(struct i2c_clie
+       return 0;
+ }
+-#if IS_ENABLED(CONFIG_OF)
+ static const struct of_device_id ov9281_of_match[] = {
+       { .compatible = "ovti,ov9281" },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, ov9281_of_match);
+-#endif
+ static const struct i2c_device_id ov9281_match_id[] = {
+       { "ovti,ov9281", 0 },
diff --git a/target/linux/bcm27xx/patches-5.4/950-0874-media-i2c-ov9281-Read-chip-ID-via-2-reads.patch b/target/linux/bcm27xx/patches-5.4/950-0874-media-i2c-ov9281-Read-chip-ID-via-2-reads.patch
new file mode 100644 (file)
index 0000000..0b06442
--- /dev/null
@@ -0,0 +1,42 @@
+From 5c6b7b60d7d607b59b4208e758180d4f93be8788 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Mon, 6 Jul 2020 17:51:32 +0100
+Subject: [PATCH] media: i2c: ov9281: Read chip ID via 2 reads
+
+Vision Components have made an OV9281 module which blocks reading
+back the majority of registers to comply with NDAs, and in doing
+so doesn't allow auto-increment register reading as used when
+reading the chip ID.
+
+Use two reads and manually combine the results.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/ov9281.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/media/i2c/ov9281.c
++++ b/drivers/media/i2c/ov9281.c
+@@ -904,13 +904,17 @@ static int ov9281_check_sensor_id(struct
+                                 struct i2c_client *client)
+ {
+       struct device *dev = &ov9281->client->dev;
+-      u32 id = 0;
++      u32 id = 0, id_msb;
+       int ret;
+-      ret = ov9281_read_reg(client, OV9281_REG_CHIP_ID,
+-                            OV9281_REG_VALUE_16BIT, &id);
+-      if (id != CHIP_ID) {
+-              dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
++      ret = ov9281_read_reg(client, OV9281_REG_CHIP_ID + 1,
++                            OV9281_REG_VALUE_08BIT, &id);
++      if (!ret)
++              ret = ov9281_read_reg(client, OV9281_REG_CHIP_ID,
++                                    OV9281_REG_VALUE_08BIT, &id_msb);
++      id |= (id_msb << 8);
++      if (ret || id != CHIP_ID) {
++              dev_err(dev, "Unexpected sensor id(%04x), ret(%d)\n", id, ret);
+               return -ENODEV;
+       }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0875-dtoverlay-Add-overlay-for-Omnivision-OV9281-image-se.patch b/target/linux/bcm27xx/patches-5.4/950-0875-dtoverlay-Add-overlay-for-Omnivision-OV9281-image-se.patch
new file mode 100644 (file)
index 0000000..c166453
--- /dev/null
@@ -0,0 +1,157 @@
+From 489b7fc3df2013766f3c4d5f682dcc7992950293 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Mon, 6 Jul 2020 17:32:21 +0100
+Subject: [PATCH] dtoverlay: Add overlay for Omnivision OV9281 image
+ sensor
+
+Adds an overlay for the OV9281 mono imaging sensor using 2 CSI-2
+data lanes.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   8 ++
+ arch/arm/boot/dts/overlays/ov9281-overlay.dts | 110 ++++++++++++++++++
+ 3 files changed, 119 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ov9281-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -115,6 +115,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       mpu6050.dtbo \
+       mz61581.dtbo \
+       ov5647.dtbo \
++      ov9281.dtbo \
+       papirus.dtbo \
+       pibell.dtbo \
+       piglow.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1813,6 +1813,14 @@ Load:   dtoverlay=ov5647
+ Params: <None>
++Name:   ov9281
++Info:   Omnivision OV9281 camera module.
++        Uses Unicam 1, which is the standard camera connector on most Pi
++        variants.
++Load:   dtoverlay=ov9281
++Params: <None>
++
++
+ Name:   papirus
+ Info:   PaPiRus ePaper Screen by Pi Supply (both HAT and pHAT)
+ Load:   dtoverlay=papirus,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts
+@@ -0,0 +1,110 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Definitions for OV9281 camera module on VC I2C bus
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c_csi_dsi>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      ov9281: ov9281@60 {
++                              compatible = "ovti,ov9281";
++                              reg = <0x60>;
++                              status = "okay";
++
++                              clocks = <&ov9281_clk>;
++                              clock-names = "xvclk";
++
++                              avdd-supply = <&ov9281_avdd>;
++                              dovdd-supply = <&ov9281_dovdd>;
++                              dvdd-supply = <&ov9281_dvdd>;
++
++                              port {
++                                      ov9281_0: endpoint {
++                                              remote-endpoint = <&csi1_ep>;
++                                              clock-lanes = <0>;
++                                              data-lanes = <1 2>;
++                                              clock-noncontinuous;
++                                              link-frequencies =
++                                                      /bits/ 64 <456000000>;
++                                      };
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&csi1>;
++              __overlay__ {
++                      status = "okay";
++
++                      port {
++                              csi1_ep: endpoint {
++                                      remote-endpoint = <&ov9281_0>;
++                                      data-lanes = <1 2>;
++                              };
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c0if>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@3 {
++              target-path="/";
++              __overlay__ {
++                      ov9281_avdd: fixedregulator@0 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "ov9281_avdd";
++                              regulator-min-microvolt = <2800000>;
++                              regulator-max-microvolt = <2800000>;
++                              gpio = <&gpio 41 GPIO_ACTIVE_HIGH>;
++                              enable-active-high;
++                      };
++                      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-path="/__overrides__";
++              __overlay__ {
++                      cam0-pwdn-ctrl = <&ov9281_avdd>,"gpio:0";
++                      cam0-pwdn      = <&ov9281_avdd>,"gpio:4";
++              };
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0876-Bluetooth-hci_bcm-Fix-RTS-handling-during-startup.patch b/target/linux/bcm27xx/patches-5.4/950-0876-Bluetooth-hci_bcm-Fix-RTS-handling-during-startup.patch
new file mode 100644 (file)
index 0000000..a288f5e
--- /dev/null
@@ -0,0 +1,33 @@
+From 44843cf006346751e42c0f4100eea7cefe61cbdf Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Sun, 6 Oct 2019 17:28:19 +0200
+Subject: [PATCH] Bluetooth: hci_bcm: Fix RTS handling during startup
+
+commit 3347a80965b38f096b1d6f995c00c9c9e53d4b8b upstream.
+
+The RPi 4 uses the hardware handshake lines for CYW43455, but the chip
+doesn't react to HCI requests during DT probe. The reason is the inproper
+handling of the RTS line during startup. According to the startup
+signaling sequence in the CYW43455 datasheet, the hosts RTS line must
+be driven after BT_REG_ON and BT_HOST_WAKE.
+
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+ drivers/bluetooth/hci_bcm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -448,9 +448,11 @@ static int bcm_open(struct hci_uart *hu)
+ out:
+       if (bcm->dev) {
++              hci_uart_set_flow_control(hu, true);
+               hu->init_speed = bcm->dev->init_speed;
+               hu->oper_speed = bcm->dev->oper_speed;
+               err = bcm_gpio_set_power(bcm->dev, true);
++              hci_uart_set_flow_control(hu, false);
+               if (err)
+                       goto err_unset_hu;
+       }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0877-Bluetooth-hci_bcm-Add-compatible-string-for-BCM43540.patch b/target/linux/bcm27xx/patches-5.4/950-0877-Bluetooth-hci_bcm-Add-compatible-string-for-BCM43540.patch
new file mode 100644 (file)
index 0000000..f429b15
--- /dev/null
@@ -0,0 +1,28 @@
+From 9ca6a4103585907a20b099f9627abfd7312f8f1c Mon Sep 17 00:00:00 2001
+From: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Date: Fri, 25 Oct 2019 14:54:26 -0700
+Subject: [PATCH] Bluetooth: hci_bcm: Add compatible string for
+ BCM43540
+
+commit d462af20dbfa1b9b1a831412f32d9d6757b82459 upstream.
+
+The BCM43540 chip is a 802.11 a/b/g/n/ac + Bluetooth 4.1 combo module.
+This patch adds a compatible string match to the serdev driver for the
+Bluetooth part of the chip.
+
+Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+ drivers/bluetooth/hci_bcm.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -1427,6 +1427,7 @@ static const struct of_device_id bcm_blu
+       { .compatible = "brcm,bcm4345c5" },
+       { .compatible = "brcm,bcm4330-bt" },
+       { .compatible = "brcm,bcm43438-bt" },
++      { .compatible = "brcm,bcm43540-bt" },
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0878-Bluetooth-btbcm-Add-entry-for-BCM4335A0-UART-bluetoo.patch b/target/linux/bcm27xx/patches-5.4/950-0878-Bluetooth-btbcm-Add-entry-for-BCM4335A0-UART-bluetoo.patch
new file mode 100644 (file)
index 0000000..e2ad19b
--- /dev/null
@@ -0,0 +1,58 @@
+From 9dcea546a8f8ccd054e693b3ab124f49886de2ab Mon Sep 17 00:00:00 2001
+From: Mohammad Rasim <mohammad.rasim96@gmail.com>
+Date: Wed, 20 Nov 2019 14:02:35 +0300
+Subject: [PATCH] Bluetooth: btbcm: Add entry for BCM4335A0 UART
+ bluetooth
+
+commit 1199ab4c9e1d4cdfbabd70b4aadbc8e72c691f65 upstream.
+
+This patch adds the device ID for the BCM4335A0 module
+(part of the AMPAK AP6335 WIFI/Bluetooth combo)
+
+hciconfig output:
+```
+hci1:   Type: Primary  Bus: UART
+        BD Address: 43:35:B0:07:1F:AC  ACL MTU: 1021:8  SCO MTU: 64:1
+        UP RUNNING
+        RX bytes:5079 acl:0 sco:0 events:567 errors:0
+        TX bytes:69065 acl:0 sco:0 commands:567 errors:0
+        Features: 0xbf 0xfe 0xcf 0xff 0xdf 0xff 0x7b 0x87
+        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
+        Link policy: RSWITCH SNIFF
+        Link mode: SLAVE ACCEPT
+        Name: 'alarm'
+        Class: 0x000000
+        Service Classes: Unspecified
+        Device Class: Miscellaneous,
+        HCI Version: 4.0 (0x6)  Revision: 0x161
+        LMP Version: 4.0 (0x6)  Subversion: 0x4106
+        Manufacturer: Broadcom Corporation (15)
+```
+
+Signed-off-by: Mohammad Rasim <mohammad.rasim96@gmail.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+ drivers/bluetooth/btbcm.c   | 1 +
+ drivers/bluetooth/hci_bcm.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/bluetooth/btbcm.c
++++ b/drivers/bluetooth/btbcm.c
+@@ -340,6 +340,7 @@ static const struct bcm_subver_table bcm
+       { 0x220e, "BCM20702A1"  },      /* 001.002.014 */
+       { 0x4217, "BCM4329B1"   },      /* 002.002.023 */
+       { 0x6106, "BCM4359C0"   },      /* 003.001.006 */
++      { 0x4106, "BCM4335A0"   },      /* 002.001.006 */
+       { }
+ };
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -1428,6 +1428,7 @@ static const struct of_device_id bcm_blu
+       { .compatible = "brcm,bcm4330-bt" },
+       { .compatible = "brcm,bcm43438-bt" },
+       { .compatible = "brcm,bcm43540-bt" },
++      { .compatible = "brcm,bcm4335a0" },
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0879-Bluetooth-hci_bcm-Disallow-set_baudrate-for-BCM4354.patch b/target/linux/bcm27xx/patches-5.4/950-0879-Bluetooth-hci_bcm-Disallow-set_baudrate-for-BCM4354.patch
new file mode 100644 (file)
index 0000000..da8f37b
--- /dev/null
@@ -0,0 +1,115 @@
+From 4c40c6ae0510be0fc9626d1717ff4163358cbfb2 Mon Sep 17 00:00:00 2001
+From: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Date: Tue, 26 Nov 2019 08:17:29 +0100
+Subject: [PATCH] Bluetooth: hci_bcm: Disallow set_baudrate for
+ BCM4354
+
+commit 5d6f391073d5c1c903ac12be72c66b96b2ae93f4 upstream.
+
+Without updating the patchram, the BCM4354 does not support a higher
+operating speed. The normal bcm_setup follows the correct order
+(init_speed, patchram and then oper_speed) but the serdev driver will
+set the operating speed before calling the hu->setup function. Thus,
+for the BCM4354, don't set the operating speed before patchram.
+
+Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
+---
+ drivers/bluetooth/hci_bcm.c | 31 +++++++++++++++++++++++++++++--
+ 1 file changed, 29 insertions(+), 2 deletions(-)
+
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -48,6 +48,14 @@
+ #define BCM_NUM_SUPPLIES 2
+ /**
++ * struct bcm_device_data - device specific data
++ * @no_early_set_baudrate: Disallow set baudrate before driver setup()
++ */
++struct bcm_device_data {
++      bool    no_early_set_baudrate;
++};
++
++/**
+  * struct bcm_device - device driver resources
+  * @serdev_hu: HCI UART controller struct
+  * @list: bcm_device_list node
+@@ -79,6 +87,7 @@
+  * @hu: pointer to HCI UART controller struct,
+  *    used to disable flow control during runtime suspend and system sleep
+  * @is_suspended: whether flow control is currently disabled
++ * @no_early_set_baudrate: don't set_baudrate before setup()
+  */
+ struct bcm_device {
+       /* Must be the first member, hci_serdev.c expects this. */
+@@ -113,6 +122,7 @@ struct bcm_device {
+       struct hci_uart         *hu;
+       bool                    is_suspended;
+ #endif
++      bool                    no_early_set_baudrate;
+ };
+ /* generic bcm uart resources */
+@@ -450,7 +460,13 @@ out:
+       if (bcm->dev) {
+               hci_uart_set_flow_control(hu, true);
+               hu->init_speed = bcm->dev->init_speed;
+-              hu->oper_speed = bcm->dev->oper_speed;
++
++              /* If oper_speed is set, ldisc/serdev will set the baudrate
++               * before calling setup()
++               */
++              if (!bcm->dev->no_early_set_baudrate)
++                      hu->oper_speed = bcm->dev->oper_speed;
++
+               err = bcm_gpio_set_power(bcm->dev, true);
+               hci_uart_set_flow_control(hu, false);
+               if (err)
+@@ -568,6 +584,8 @@ static int bcm_setup(struct hci_uart *hu
+       /* Operational speed if any */
+       if (hu->oper_speed)
+               speed = hu->oper_speed;
++      else if (bcm->dev && bcm->dev->oper_speed)
++              speed = bcm->dev->oper_speed;
+       else if (hu->proto->oper_speed)
+               speed = hu->proto->oper_speed;
+       else
+@@ -1377,6 +1395,7 @@ static struct platform_driver bcm_driver
+ static int bcm_serdev_probe(struct serdev_device *serdev)
+ {
+       struct bcm_device *bcmdev;
++      const struct bcm_device_data *data;
+       int err;
+       bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL);
+@@ -1411,6 +1430,10 @@ static int bcm_serdev_probe(struct serde
+       if (err)
+               dev_err(&serdev->dev, "Failed to power down\n");
++      data = device_get_match_data(bcmdev->dev);
++      if (data)
++              bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;
++
+       return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
+ }
+@@ -1422,12 +1445,16 @@ static void bcm_serdev_remove(struct ser
+ }
+ #ifdef CONFIG_OF
++static struct bcm_device_data bcm4354_device_data = {
++      .no_early_set_baudrate = true,
++};
++
+ static const struct of_device_id bcm_bluetooth_of_match[] = {
+       { .compatible = "brcm,bcm20702a1" },
+       { .compatible = "brcm,bcm4345c5" },
+       { .compatible = "brcm,bcm4330-bt" },
+       { .compatible = "brcm,bcm43438-bt" },
+-      { .compatible = "brcm,bcm43540-bt" },
++      { .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
+       { .compatible = "brcm,bcm4335a0" },
+       { },
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0880-Bluetooth-btbcm-Support-pcm-configuration.patch b/target/linux/bcm27xx/patches-5.4/950-0880-Bluetooth-btbcm-Support-pcm-configuration.patch
new file mode 100644 (file)
index 0000000..2d40e7f
--- /dev/null
@@ -0,0 +1,124 @@
+From 6631d2076af26d2b5b6a3a2f17e8a33de48abcac Mon Sep 17 00:00:00 2001
+From: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Date: Tue, 26 Nov 2019 08:17:30 +0100
+Subject: [PATCH] Bluetooth: btbcm: Support pcm configuration
+
+commit 528379902337102b0264fe5343eafb3d6c59fa45 upstream.
+
+Add BCM vendor specific command to configure PCM parameters. The new
+vendor opcode allows us to set the sco routing, the pcm interface rate,
+and a few other pcm specific options (frame sync, sync mode, and clock
+mode). See broadcom-bluetooth.txt in Documentation for more information
+about valid values for those settings.
+
+Here is an example trace where this opcode was used to configure
+a BCM4354:
+
+        < HCI Command: Vendor (0x3f|0x001c) plen 5
+                01 02 00 01 01
+        > HCI Event: Command Complete (0x0e) plen 4
+        Vendor (0x3f|0x001c) ncmd 1
+                Status: Success (0x00)
+
+We can read back the values as well with ocf 0x001d to confirm the
+values that were set:
+        $ hcitool cmd 0x3f 0x001d
+        < HCI Command: ogf 0x3f, ocf 0x001d, plen 0
+        > HCI Event: 0x0e plen 9
+        01 1D FC 00 01 02 00 01 01
+
+Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
+---
+ drivers/bluetooth/btbcm.c | 46 +++++++++++++++++++++++++++++++++++++++
+ drivers/bluetooth/btbcm.h | 16 ++++++++++++++
+ 2 files changed, 62 insertions(+)
+
+--- a/drivers/bluetooth/btbcm.c
++++ b/drivers/bluetooth/btbcm.c
+@@ -105,6 +105,52 @@ int btbcm_set_bdaddr(struct hci_dev *hde
+ }
+ EXPORT_SYMBOL_GPL(btbcm_set_bdaddr);
++int btbcm_read_pcm_int_params(struct hci_dev *hdev,
++                            struct bcm_set_pcm_int_params *params)
++{
++      struct sk_buff *skb;
++      int err = 0;
++
++      skb = __hci_cmd_sync(hdev, 0xfc1d, 0, NULL, HCI_INIT_TIMEOUT);
++      if (IS_ERR(skb)) {
++              err = PTR_ERR(skb);
++              bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)", err);
++              return err;
++      }
++
++      if (skb->len != 6 || skb->data[0]) {
++              bt_dev_err(hdev, "BCM: Read PCM int params length mismatch");
++              kfree_skb(skb);
++              return -EIO;
++      }
++
++      if (params)
++              memcpy(params, skb->data + 1, 5);
++
++      kfree_skb(skb);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params);
++
++int btbcm_write_pcm_int_params(struct hci_dev *hdev,
++                             const struct bcm_set_pcm_int_params *params)
++{
++      struct sk_buff *skb;
++      int err;
++
++      skb = __hci_cmd_sync(hdev, 0xfc1c, 5, params, HCI_INIT_TIMEOUT);
++      if (IS_ERR(skb)) {
++              err = PTR_ERR(skb);
++              bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)", err);
++              return err;
++      }
++      kfree_skb(skb);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params);
++
+ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
+ {
+       const struct hci_command_hdr *cmd;
+--- a/drivers/bluetooth/btbcm.h
++++ b/drivers/bluetooth/btbcm.h
+@@ -54,6 +54,10 @@ struct bcm_set_pcm_format_params {
+ int btbcm_check_bdaddr(struct hci_dev *hdev);
+ int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw);
++int btbcm_read_pcm_int_params(struct hci_dev *hdev,
++                            struct bcm_set_pcm_int_params *params);
++int btbcm_write_pcm_int_params(struct hci_dev *hdev,
++                             const struct bcm_set_pcm_int_params *params);
+ int btbcm_setup_patchram(struct hci_dev *hdev);
+ int btbcm_setup_apple(struct hci_dev *hdev);
+@@ -73,6 +77,18 @@ static inline int btbcm_set_bdaddr(struc
+ {
+       return -EOPNOTSUPP;
+ }
++
++int btbcm_read_pcm_int_params(struct hci_dev *hdev,
++                            struct bcm_set_pcm_int_params *params)
++{
++      return -EOPNOTSUPP;
++}
++
++int btbcm_write_pcm_int_params(struct hci_dev *hdev,
++                             const struct bcm_set_pcm_int_params *params)
++{
++      return -EOPNOTSUPP;
++}
+ static inline int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw)
+ {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0881-Bluetooth-hci_bcm-Support-pcm-params-in-dts.patch b/target/linux/bcm27xx/patches-5.4/950-0881-Bluetooth-hci_bcm-Support-pcm-params-in-dts.patch
new file mode 100644 (file)
index 0000000..fa2de56
--- /dev/null
@@ -0,0 +1,74 @@
+From 8b4d7321625cc8403a9ce7f050bd8d1b4ef7446d Mon Sep 17 00:00:00 2001
+From: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Date: Tue, 26 Nov 2019 08:17:32 +0100
+Subject: [PATCH] Bluetooth: hci_bcm: Support pcm params in dts
+
+commit eb762b94111b646b4f116ebfdbfcadbad14e12b3 upstream.
+
+BCM chips may require configuration of PCM to operate correctly and
+there is a vendor specific HCI command to do this. Add support in the
+hci_bcm driver to parse this from devicetree and configure the chip.
+
+Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
+---
+ drivers/bluetooth/hci_bcm.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -123,6 +123,7 @@ struct bcm_device {
+       bool                    is_suspended;
+ #endif
+       bool                    no_early_set_baudrate;
++      u8                      pcm_int_params[5];
+ };
+ /* generic bcm uart resources */
+@@ -597,6 +598,16 @@ static int bcm_setup(struct hci_uart *hu
+                       host_set_baudrate(hu, speed);
+       }
++      /* PCM parameters if provided */
++      if (bcm->dev && bcm->dev->pcm_int_params[0] != 0xff) {
++              struct bcm_set_pcm_int_params params;
++
++              btbcm_read_pcm_int_params(hu->hdev, &params);
++
++              memcpy(&params, bcm->dev->pcm_int_params, 5);
++              btbcm_write_pcm_int_params(hu->hdev, &params);
++      }
++
+ finalize:
+       release_firmware(fw);
+@@ -1134,6 +1145,8 @@ static int bcm_acpi_probe(struct bcm_dev
+ static int bcm_of_probe(struct bcm_device *bdev)
+ {
+       device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
++      device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params",
++                                    bdev->pcm_int_params, 5);
+       return 0;
+ }
+@@ -1149,6 +1162,9 @@ static int bcm_probe(struct platform_dev
+       dev->dev = &pdev->dev;
+       dev->irq = platform_get_irq(pdev, 0);
++      /* Initialize routing field to an unused value */
++      dev->pcm_int_params[0] = 0xff;
++
+       if (has_acpi_companion(&pdev->dev)) {
+               ret = bcm_acpi_probe(dev);
+               if (ret)
+@@ -1409,6 +1425,9 @@ static int bcm_serdev_probe(struct serde
+       bcmdev->serdev_hu.serdev = serdev;
+       serdev_device_set_drvdata(serdev, bcmdev);
++      /* Initialize routing field to an unused value */
++      bcmdev->pcm_int_params[0] = 0xff;
++
+       if (has_acpi_companion(&serdev->dev))
+               err = bcm_acpi_probe(bcmdev);
+       else
diff --git a/target/linux/bcm27xx/patches-5.4/950-0882-Bluetooth-hci_bcm-Drive-RTS-only-for-BCM43438.patch b/target/linux/bcm27xx/patches-5.4/950-0882-Bluetooth-hci_bcm-Drive-RTS-only-for-BCM43438.patch
new file mode 100644 (file)
index 0000000..507f21a
--- /dev/null
@@ -0,0 +1,92 @@
+From b2e19dbff471eb6b9b39ff8f21c8d38e4fac8fe6 Mon Sep 17 00:00:00 2001
+From: Stefan Wahren <wahrenst@gmx.net>
+Date: Wed, 1 Jan 2020 15:01:34 +0100
+Subject: [PATCH] Bluetooth: hci_bcm: Drive RTS only for BCM43438
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit e601daed271e9eb1b923972a0a1af65f8c7bb77b upstream.
+
+The commit 3347a80965b3 ("Bluetooth: hci_bcm: Fix RTS handling during
+startup") is causing at least a regression for AP6256 on Orange Pi 3.
+So do the RTS line handing during startup only on the necessary platform.
+
+Fixes: 3347a80965b3 ("Bluetooth: hci_bcm: Fix RTS handling during startup")
+Reported-by: Ondřej Jirman <megous@megous.com>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+ drivers/bluetooth/hci_bcm.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+--- a/drivers/bluetooth/hci_bcm.c
++++ b/drivers/bluetooth/hci_bcm.c
+@@ -53,6 +53,7 @@
+  */
+ struct bcm_device_data {
+       bool    no_early_set_baudrate;
++      bool    drive_rts_on_open;
+ };
+ /**
+@@ -123,6 +124,7 @@ struct bcm_device {
+       bool                    is_suspended;
+ #endif
+       bool                    no_early_set_baudrate;
++      bool                    drive_rts_on_open;
+       u8                      pcm_int_params[5];
+ };
+@@ -459,7 +461,9 @@ static int bcm_open(struct hci_uart *hu)
+ out:
+       if (bcm->dev) {
+-              hci_uart_set_flow_control(hu, true);
++              if (bcm->dev->drive_rts_on_open)
++                      hci_uart_set_flow_control(hu, true);
++
+               hu->init_speed = bcm->dev->init_speed;
+               /* If oper_speed is set, ldisc/serdev will set the baudrate
+@@ -469,7 +473,10 @@ out:
+                       hu->oper_speed = bcm->dev->oper_speed;
+               err = bcm_gpio_set_power(bcm->dev, true);
+-              hci_uart_set_flow_control(hu, false);
++
++              if (bcm->dev->drive_rts_on_open)
++                      hci_uart_set_flow_control(hu, false);
++
+               if (err)
+                       goto err_unset_hu;
+       }
+@@ -1450,8 +1457,10 @@ static int bcm_serdev_probe(struct serde
+               dev_err(&serdev->dev, "Failed to power down\n");
+       data = device_get_match_data(bcmdev->dev);
+-      if (data)
++      if (data) {
+               bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;
++              bcmdev->drive_rts_on_open = data->drive_rts_on_open;
++      }
+       return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
+ }
+@@ -1468,11 +1477,15 @@ static struct bcm_device_data bcm4354_de
+       .no_early_set_baudrate = true,
+ };
++static struct bcm_device_data bcm43438_device_data = {
++      .drive_rts_on_open = true,
++};
++
+ static const struct of_device_id bcm_bluetooth_of_match[] = {
+       { .compatible = "brcm,bcm20702a1" },
+       { .compatible = "brcm,bcm4345c5" },
+       { .compatible = "brcm,bcm4330-bt" },
+-      { .compatible = "brcm,bcm43438-bt" },
++      { .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
+       { .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
+       { .compatible = "brcm,bcm4335a0" },
+       { },
diff --git a/target/linux/bcm27xx/patches-5.4/950-0883-Enhances-the-DAC-driver-to-control-the-optional-head.patch b/target/linux/bcm27xx/patches-5.4/950-0883-Enhances-the-DAC-driver-to-control-the-optional-head.patch
new file mode 100644 (file)
index 0000000..1289060
--- /dev/null
@@ -0,0 +1,134 @@
+From defa915bf0acf6ab5e56997a6733546c33f87682 Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joerg@i2audio.com>
+Date: Tue, 7 Jul 2020 15:09:06 +0200
+Subject: [PATCH] Enhances the DAC+ driver to control the optional
+ headphone amplifier
+
+Probes on the I2C bus for TPA6130A2, if successful, it sets DT-parameter
+'status' from 'disabled' to 'okay' using change_sets to enable
+the headphone control.
+
+Signed-off-by: Joerg Schambacher joerg@i2audio.com
+---
+ sound/soc/bcm/Kconfig             |  1 +
+ sound/soc/bcm/hifiberry_dacplus.c | 68 ++++++++++++++++++++++++++++++-
+ 2 files changed, 67 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -38,6 +38,7 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
+         tristate "Support for HifiBerry DAC+"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+         select SND_SOC_PCM512x
++        select SND_SOC_TPA6130A2
+         select COMMON_CLK_HIFIBERRY_DACPRO
+         help
+          Say Y or M if you want to add support for HifiBerry DAC+.
+--- a/sound/soc/bcm/hifiberry_dacplus.c
++++ b/sound/soc/bcm/hifiberry_dacplus.c
+@@ -4,6 +4,7 @@
+  * Author:    Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
+  *            Copyright 2014-2015
+  *            based on code by Florian Meier <florian.meier@koalo.de>
++ *            Headphone added by Joerg Schambacher, joerg@i2audio.com
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+@@ -24,6 +25,7 @@
+ #include <linux/of.h>
+ #include <linux/slab.h>
+ #include <linux/delay.h>
++#include <linux/i2c.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+@@ -177,8 +179,7 @@ static int snd_rpi_hifiberry_dacplus_ini
+       else
+               snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+-      if (digital_gain_0db_limit)
+-      {
++      if (digital_gain_0db_limit) {
+               int ret;
+               struct snd_soc_card *card = rtd->card;
+@@ -292,6 +293,15 @@ static struct snd_soc_dai_link snd_rpi_h
+ },
+ };
++/* aux device for optional headphone amp */
++static struct snd_soc_aux_dev hifiberry_dacplus_aux_devs[] = {
++      {
++              .dlc = {
++                      .name = "tpa6130a2.1-0060",
++              },
++      },
++};
++
+ /* audio machine driver */
+ static struct snd_soc_card snd_rpi_hifiberry_dacplus = {
+       .name         = "snd_rpi_hifiberry_dacplus",
+@@ -301,9 +311,63 @@ static struct snd_soc_card snd_rpi_hifib
+       .num_links    = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai),
+ };
++static int hb_hp_detect(void)
++{
++      struct i2c_adapter *adap = i2c_get_adapter(1);
++      int ret;
++
++      struct i2c_client tpa_i2c_client = {
++              .addr = 0x60,
++              .adapter = adap,
++      };
++
++      ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
++      i2c_put_adapter(adap);
++      return ret;
++};
++
++static struct property tpa_enable_prop = {
++             .name = "status",
++             .length = 4 + 1, /* length 'okay' + 1 */
++             .value = "okay",
++      };
++
+ static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev)
+ {
+       int ret = 0;
++      struct snd_soc_card *card = &snd_rpi_hifiberry_dacplus;
++      int len;
++      struct device_node *tpa_node;
++      struct property *tpa_prop;
++      struct of_changeset ocs;
++
++      /* probe for head phone amp */
++      if (hb_hp_detect()) {
++              card->aux_dev = hifiberry_dacplus_aux_devs;
++              card->num_aux_devs =
++                              ARRAY_SIZE(hifiberry_dacplus_aux_devs);
++              tpa_node = of_find_compatible_node(NULL, NULL, "ti,tpa6130a2");
++              tpa_prop = of_find_property(tpa_node, "status", &len);
++
++              if (strcmp((char *)tpa_prop->value, "okay")) {
++                      /* and activate headphone using change_sets */
++                      dev_info(&pdev->dev, "activating headphone amplifier");
++                      of_changeset_init(&ocs);
++                      ret = of_changeset_update_property(&ocs, tpa_node,
++                                                      &tpa_enable_prop);
++                      if (ret) {
++                              dev_err(&pdev->dev,
++                              "cannot activate headphone amplifier\n");
++                              return -ENODEV;
++                      }
++                      ret = of_changeset_apply(&ocs);
++                      if (ret) {
++                              dev_err(&pdev->dev,
++                              "cannot activate headphone amplifier\n");
++                              return -ENODEV;
++                      }
++              }
++      }
+       snd_rpi_hifiberry_dacplus.dev = &pdev->dev;
+       if (pdev->dev.of_node) {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0884-ARM-dts-hifiberry-dacplus-headphone-amp-support.patch b/target/linux/bcm27xx/patches-5.4/950-0884-ARM-dts-hifiberry-dacplus-headphone-amp-support.patch
new file mode 100644 (file)
index 0000000..937d104
--- /dev/null
@@ -0,0 +1,24 @@
+From 3295a6b483ea507f8e5d19a806b7db1da1f5a567 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 8 Jul 2020 17:33:06 +0100
+Subject: [PATCH] ARM: dts: hifiberry-dacplus headphone amp support
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts
+@@ -39,6 +39,11 @@
+                               CPVDD-supply = <&vdd_3v3_reg>;
+                               status = "okay";
+                       };
++                      hpamp: hpamp@60 {
++                              compatible = "ti,tpa6130a2";
++                              reg = <0x60>;
++                              status = "disabled";
++                      };
+               };
+       };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0885-media-i2c-imx290-Explicitly-set-v-h-blank-on-mode-ch.patch b/target/linux/bcm27xx/patches-5.4/950-0885-media-i2c-imx290-Explicitly-set-v-h-blank-on-mode-ch.patch
new file mode 100644 (file)
index 0000000..751f46d
--- /dev/null
@@ -0,0 +1,46 @@
+From 0a47c61cee411b3ada4413f6cebae8cdb06f062e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 10:31:53 +0100
+Subject: [PATCH] media: i2c: imx290: Explicitly set v&h blank on
+ mode change
+
+__v4l2_ctrl_modify_range only updates the current value should
+it be invalid within the new range. That can leave modes producing
+odd frame rates.
+
+Explicitly update the HBLANK and VBLANK values so that on mode
+change we revert to the default frame rate for the mode.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -796,17 +796,23 @@ static int imx290_set_fmt(struct v4l2_su
+                       __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
+                                                imx290_calc_pixel_rate(imx290));
+-              if (imx290->hblank)
++              if (imx290->hblank) {
+                       __v4l2_ctrl_modify_range(imx290->hblank,
+                                                imx290->hmax_min - mode->width,
+                                                IMX290_HMAX_MAX - mode->width,
+                                                1, mode->hmax - mode->width);
+-              if (imx290->vblank)
++                      __v4l2_ctrl_s_ctrl(imx290->hblank,
++                                         mode->hmax - mode->width);
++              }
++              if (imx290->vblank) {
+                       __v4l2_ctrl_modify_range(imx290->vblank,
+                                                mode->vmax - mode->height,
+                                                IMX290_VMAX_MAX - mode->height,
+                                                1,
+                                                mode->vmax - mode->height);
++                      __v4l2_ctrl_s_ctrl(imx290->vblank,
++                                         mode->vmax - mode->height);
++              }
+               if (imx290->exposure)
+                       __v4l2_ctrl_modify_range(imx290->exposure,
+                                                mode->vmax - mode->height,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0886-media-i2c-imx290-Add-support-for-g_selection-to-repo.patch b/target/linux/bcm27xx/patches-5.4/950-0886-media-i2c-imx290-Add-support-for-g_selection-to-repo.patch
new file mode 100644 (file)
index 0000000..86680af
--- /dev/null
@@ -0,0 +1,156 @@
+From a191c6d6e5180f54ecf16adda61988a16ce9fe48 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 11:23:48 +0100
+Subject: [PATCH] media: i2c: imx290: Add support for g_selection to
+ report cropping
+
+Userspace needs to know the cropping arrangements for each mode,
+so expose this through g_selection.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 84 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -61,6 +61,13 @@ enum imx290_clk_index {
+ #define IMX290_PGCTRL_THRU BIT(1)
+ #define IMX290_PGCTRL_MODE(n) ((n) << 4)
++#define IMX290_NATIVE_WIDTH           1945U
++#define IMX290_NATIVE_HEIGHT          1109U
++#define IMX290_PIXEL_ARRAY_LEFT               4U
++#define IMX290_PIXEL_ARRAY_TOP                12U
++#define IMX290_PIXEL_ARRAY_WIDTH      1937U
++#define IMX290_PIXEL_ARRAY_HEIGHT     1097U
++
+ static const char * const imx290_supply_name[] = {
+       "vdda",
+       "vddd",
+@@ -80,6 +87,7 @@ struct imx290_mode {
+       u32 hmax;
+       u32 vmax;
+       u8 link_freq_index;
++      struct v4l2_rect crop;
+       const struct imx290_regval *data;
+       u32 data_size;
+@@ -384,6 +392,12 @@ static const struct imx290_mode imx290_m
+               .hmax = 0x1130,
+               .vmax = 0x0465,
+               .link_freq_index = FREQ_INDEX_1080P,
++              .crop = {
++                      .left = 4 + 8,
++                      .top = 12 + 8,
++                      .width = 1920,
++                      .height = 1080,
++              },
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+               .clk_data = {
+@@ -398,6 +412,12 @@ static const struct imx290_mode imx290_m
+               .hmax = 0x19c8,
+               .vmax = 0x02ee,
+               .link_freq_index = FREQ_INDEX_720P,
++              .crop = {
++                      .left = 4 + 8 + 320,
++                      .top = 12 + 8 + 180,
++                      .width = 1280,
++                      .height = 720,
++              },
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+               .clk_data = {
+@@ -415,6 +435,12 @@ static const struct imx290_mode imx290_m
+               .hmax = 0x0898,
+               .vmax = 0x0465,
+               .link_freq_index = FREQ_INDEX_1080P,
++              .crop = {
++                      .left = 4 + 8,
++                      .top = 12 + 8,
++                      .width = 1920,
++                      .height = 1080,
++              },
+               .data = imx290_1080p_settings,
+               .data_size = ARRAY_SIZE(imx290_1080p_settings),
+               .clk_data = {
+@@ -429,6 +455,12 @@ static const struct imx290_mode imx290_m
+               .hmax = 0x0ce4,
+               .vmax = 0x02ee,
+               .link_freq_index = FREQ_INDEX_720P,
++              .crop = {
++                      .left = 4 + 8 + 320,
++                      .top = 12 + 8 + 180,
++                      .width = 1280,
++                      .height = 720,
++              },
+               .data = imx290_720p_settings,
+               .data_size = ARRAY_SIZE(imx290_720p_settings),
+               .clk_data = {
+@@ -875,6 +907,57 @@ static int imx290_write_current_format(s
+       return 0;
+ }
++static const struct v4l2_rect *
++__imx290_get_pad_crop(struct imx290 *imx290, struct v4l2_subdev_pad_config *cfg,
++                    unsigned int pad, enum v4l2_subdev_format_whence which)
++{
++      switch (which) {
++      case V4L2_SUBDEV_FORMAT_TRY:
++              return v4l2_subdev_get_try_crop(&imx290->sd, cfg, pad);
++      case V4L2_SUBDEV_FORMAT_ACTIVE:
++              return &imx290->current_mode->crop;
++      }
++
++      return NULL;
++}
++
++static int imx290_get_selection(struct v4l2_subdev *sd,
++                              struct v4l2_subdev_pad_config *cfg,
++                              struct v4l2_subdev_selection *sel)
++{
++      switch (sel->target) {
++      case V4L2_SEL_TGT_CROP: {
++              struct imx290 *imx290 = to_imx290(sd);
++
++              mutex_lock(&imx290->lock);
++              sel->r = *__imx290_get_pad_crop(imx290, cfg, sel->pad,
++                                              sel->which);
++              mutex_unlock(&imx290->lock);
++
++              return 0;
++      }
++
++      case V4L2_SEL_TGT_NATIVE_SIZE:
++              sel->r.top = 0;
++              sel->r.left = 0;
++              sel->r.width = IMX290_NATIVE_WIDTH;
++              sel->r.height = IMX290_NATIVE_HEIGHT;
++
++              return 0;
++
++      case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
++              sel->r.top = IMX290_PIXEL_ARRAY_TOP;
++              sel->r.left = IMX290_PIXEL_ARRAY_LEFT;
++              sel->r.width = IMX290_PIXEL_ARRAY_WIDTH;
++              sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
++
++              return 0;
++      }
++
++      return -EINVAL;
++}
++
+ /* Start streaming */
+ static int imx290_start_streaming(struct imx290 *imx290)
+ {
+@@ -1073,6 +1156,7 @@ static const struct v4l2_subdev_pad_ops
+       .enum_frame_size = imx290_enum_frame_size,
+       .get_fmt = imx290_get_fmt,
+       .set_fmt = imx290_set_fmt,
++      .get_selection = imx290_get_selection,
+ };
+ static const struct v4l2_subdev_ops imx290_subdev_ops = {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0887-media-i2c-imx290-Set-the-colorspace-fields-in-the-fo.patch b/target/linux/bcm27xx/patches-5.4/950-0887-media-i2c-imx290-Set-the-colorspace-fields-in-the-fo.patch
new file mode 100644 (file)
index 0000000..28c43cd
--- /dev/null
@@ -0,0 +1,31 @@
+From b02ddac32c2bcd8894dac22de7ef1fb80a4dfe1a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 11:51:26 +0100
+Subject: [PATCH] media: i2c: imx290: Set the colorspace fields in
+ the format
+
+The colorspace fields were left untouched in imx290_set_fmt
+which lead to a v4l2-compliance failure.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -813,6 +813,14 @@ static int imx290_set_fmt(struct v4l2_su
+       fmt->format.code = imx290->formats[i].code;
+       fmt->format.field = V4L2_FIELD_NONE;
++      fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
++      fmt->format.ycbcr_enc =
++                      V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
++      fmt->format.quantization =
++              V4L2_MAP_QUANTIZATION_DEFAULT(true, fmt->format.colorspace,
++                                            fmt->format.ycbcr_enc);
++      fmt->format.xfer_func =
++              V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               format = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0888-media-bcm2835-unicam-Reinstate-V4L2_CAP_READWRITE-in.patch b/target/linux/bcm27xx/patches-5.4/950-0888-media-bcm2835-unicam-Reinstate-V4L2_CAP_READWRITE-in.patch
new file mode 100644 (file)
index 0000000..5b2b280
--- /dev/null
@@ -0,0 +1,28 @@
+From 6253cd2eee555c6b2779667cc41ee1d75aa85034 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 14:23:40 +0100
+Subject: [PATCH] media: bcm2835-unicam: Reinstate V4L2_CAP_READWRITE
+ in the caps
+
+v4l2-compliance throws a failure if the device doesn't advertise
+V4L2_CAP_READWRITE but allows read or write operations.
+We do support read, so reinstate the flag.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -2416,8 +2416,8 @@ static int register_node(struct unicam_d
+       vdev->queue = q;
+       vdev->lock = &node->lock;
+       vdev->device_caps = (pad_id == IMAGE_PAD) ?
+-                          (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING) :
+-                          (V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING);
++                              V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_META_CAPTURE;
++      vdev->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       /* Define the device names */
+       snprintf(vdev->name, sizeof(vdev->name), "%s-%s", UNICAM_MODULE_NAME,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0889-media-bcm2835-unicam-Ensure-type-is-VIDEO_CAPTURE-in.patch b/target/linux/bcm27xx/patches-5.4/950-0889-media-bcm2835-unicam-Ensure-type-is-VIDEO_CAPTURE-in.patch
new file mode 100644 (file)
index 0000000..1e8407f
--- /dev/null
@@ -0,0 +1,36 @@
+From 470e49cf5ee0b77e6812595ca396e34af8ae67b4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 14:52:43 +0100
+Subject: [PATCH] media: bcm2835-unicam: Ensure type is VIDEO_CAPTURE
+ in [g|s]_selection
+
+[g|s]_selection pass in a buffer type that needs to be validated
+before passing on to the sensor subdev.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1880,6 +1880,9 @@ static int unicam_s_selection(struct fil
+               .r = sel->r,
+       };
++      if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++              return -EINVAL;
++
+       return v4l2_subdev_call(dev->sensor, pad, set_selection, NULL, &sdsel);
+ }
+@@ -1894,6 +1897,9 @@ static int unicam_g_selection(struct fil
+       };
+       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;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0890-dtoverlays-Create-an-overlay-for-the-Omnivision-OV72.patch b/target/linux/bcm27xx/patches-5.4/950-0890-dtoverlays-Create-an-overlay-for-the-Omnivision-OV72.patch
new file mode 100644 (file)
index 0000000..6a4da8f
--- /dev/null
@@ -0,0 +1,157 @@
+From 870de3bc0e80a9b79b470a45636437a0078041c1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 16:12:05 +0100
+Subject: [PATCH] dtoverlays: Create an overlay for the Omnivision
+ OV7251 sensor
+
+Adds an overlay for the OV7251 VGA global shutter sensor.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   8 ++
+ arch/arm/boot/dts/overlays/ov7251-overlay.dts | 111 ++++++++++++++++++
+ 3 files changed, 120 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ov7251-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -115,6 +115,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       mpu6050.dtbo \
+       mz61581.dtbo \
+       ov5647.dtbo \
++      ov7251.dtbo \
+       ov9281.dtbo \
+       papirus.dtbo \
+       pibell.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1813,6 +1813,14 @@ Load:   dtoverlay=ov5647
+ Params: <None>
++Name:   ov7251
++Info:   Omnivision OV7251 camera module.
++        Uses Unicam 1, which is the standard camera connector on most Pi
++        variants.
++Load:   dtoverlay=ov7251
++Params: <None>
++
++
+ Name:   ov9281
+ Info:   Omnivision OV9281 camera module.
+         Uses Unicam 1, which is the standard camera connector on most Pi
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ov7251-overlay.dts
+@@ -0,0 +1,111 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Definitions for OV7251 camera module on VC I2C bus
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c_csi_dsi>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      ov7251: ov7251@60 {
++                              compatible = "ovti,ov7251";
++                              reg = <0x60>;
++                              status = "okay";
++
++                              clocks = <&ov7251_clk>;
++                              clock-names = "xclk";
++                              clock-frequency = <24000000>;
++
++                              vdddo-supply = <&ov7251_dovdd>;
++                              vdda-supply = <&ov7251_avdd>;
++                              vddd-supply = <&ov7251_dvdd>;
++
++                              enable-gpios = <&gpio 41 GPIO_ACTIVE_HIGH>;
++
++                              port {
++                                      ov7251_0: endpoint {
++                                              remote-endpoint = <&csi1_ep>;
++                                              clock-lanes = <0>;
++                                              data-lanes = <1>;
++                                              clock-noncontinuous;
++                                              link-frequencies =
++                                                      /bits/ 64 <456000000>;
++                                      };
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&csi1>;
++              __overlay__ {
++                      status = "okay";
++
++                      port {
++                              csi1_ep: endpoint {
++                                      remote-endpoint = <&ov7251_0>;
++                                      data-lanes = <1>;
++                              };
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c0if>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@3 {
++              target-path="/";
++              __overlay__ {
++                      ov7251_avdd: fixedregulator@0 {
++                              compatible = "regulator-fixed";
++                              regulator-name = "ov7251_avdd";
++                              regulator-min-microvolt = <2800000>;
++                              regulator-max-microvolt = <2800000>;
++                      };
++                      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-path="/__overrides__";
++              __overlay__ {
++                      cam0-pwdn-ctrl = <&ov7251>,"enable-gpios:0";
++                      cam0-pwdn      = <&ov7251>,"enable-gpios:4";
++              };
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0891-vc4_hdmi-Set-HDMI_MAI_FMT.patch b/target/linux/bcm27xx/patches-5.4/950-0891-vc4_hdmi-Set-HDMI_MAI_FMT.patch
new file mode 100644 (file)
index 0000000..2c305a0
--- /dev/null
@@ -0,0 +1,124 @@
+From c9ba62745ba17d21542db28bf7dc28a39e19f7c2 Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Tue, 10 Mar 2020 22:21:15 +0000
+Subject: [PATCH] vc4_hdmi: Set HDMI_MAI_FMT
+
+The hardware uses this for generating the right audio
+data island packets when using formats other than PCM
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 47 ++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_regs.h | 31 ++++++++++++++++++++++
+ 2 files changed, 78 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -917,6 +917,45 @@ static void vc4_hdmi_audio_shutdown(stru
+       vc4_hdmi->audio.substream = NULL;
+ }
++static int sample_rate_to_mai_fmt(int samplerate)
++{
++   switch(samplerate)
++   {
++      case 8000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_8000;
++      case 11025:
++         return VC4_HDMI_MAI_SAMPLE_RATE_11025;
++      case 12000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_12000;
++      case 16000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_16000;
++      case 22050:
++         return VC4_HDMI_MAI_SAMPLE_RATE_22050;
++      case 24000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_24000;
++      case 32000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_32000;
++      case 44100:
++         return VC4_HDMI_MAI_SAMPLE_RATE_44100;
++      case 48000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_48000;
++      case 64000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_64000;
++      case 88200:
++         return VC4_HDMI_MAI_SAMPLE_RATE_88200;
++      case 96000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_96000;
++      case 128000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_128000;
++      case 176400:
++         return VC4_HDMI_MAI_SAMPLE_RATE_176400;
++      case 192000:
++         return VC4_HDMI_MAI_SAMPLE_RATE_192000;
++      default:
++         return VC4_HDMI_MAI_SAMPLE_RATE_NOT_INDICATED;
++   }
++}
++
+ /* HDMI audio codec callbacks */
+ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *params,
+@@ -926,6 +965,8 @@ static int vc4_hdmi_audio_hw_params(stru
+       struct device *dev = &vc4_hdmi->pdev->dev;
+       u32 audio_packet_config, channel_mask;
+       u32 channel_map;
++      u32 mai_audio_format;
++      u32 mai_sample_rate;
+       if (substream != vc4_hdmi->audio.substream)
+               return -EINVAL;
+@@ -946,6 +987,12 @@ static int vc4_hdmi_audio_hw_params(stru
+       vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
++      mai_sample_rate = sample_rate_to_mai_fmt(vc4_hdmi->audio.samplerate);
++      mai_audio_format = VC4_HDMI_MAI_FORMAT_PCM;
++      HDMI_WRITE(HDMI_MAI_FMT,
++              VC4_SET_FIELD(mai_sample_rate, VC4_HDMI_MAI_FORMAT_SAMPLE_RATE) |
++              VC4_SET_FIELD(mai_audio_format, VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT));
++
+       /* The B frame identifier should match the value used by alsa-lib (8) */
+       audio_packet_config =
+               VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
+--- a/drivers/gpu/drm/vc4/vc4_regs.h
++++ b/drivers/gpu/drm/vc4/vc4_regs.h
+@@ -516,6 +516,37 @@
+ # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK                  VC4_MASK(7, 0)
+ # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT                 0
++
++# define VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT_MASK                VC4_MASK(23, 16)
++# define VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT_SHIFT               16
++
++enum {
++      VC4_HDMI_MAI_FORMAT_PCM = 2,
++      VC4_HDMI_MAI_FORMAT_HBR = 200,
++};
++
++# define VC4_HDMI_MAI_FORMAT_SAMPLE_RATE_MASK         VC4_MASK(15, 8)
++# define VC4_HDMI_MAI_FORMAT_SAMPLE_RATE_SHIFT                8
++
++enum {
++      VC4_HDMI_MAI_SAMPLE_RATE_NOT_INDICATED = 0,
++      VC4_HDMI_MAI_SAMPLE_RATE_8000 = 1,
++      VC4_HDMI_MAI_SAMPLE_RATE_11025 = 2,
++      VC4_HDMI_MAI_SAMPLE_RATE_12000 = 3,
++      VC4_HDMI_MAI_SAMPLE_RATE_16000 = 4,
++      VC4_HDMI_MAI_SAMPLE_RATE_22050 = 5,
++      VC4_HDMI_MAI_SAMPLE_RATE_24000 = 6,
++      VC4_HDMI_MAI_SAMPLE_RATE_32000 = 7,
++      VC4_HDMI_MAI_SAMPLE_RATE_44100 = 8,
++      VC4_HDMI_MAI_SAMPLE_RATE_48000 = 9,
++      VC4_HDMI_MAI_SAMPLE_RATE_64000 = 10,
++      VC4_HDMI_MAI_SAMPLE_RATE_88200 = 11,
++      VC4_HDMI_MAI_SAMPLE_RATE_96000 = 12,
++      VC4_HDMI_MAI_SAMPLE_RATE_128000 = 13,
++      VC4_HDMI_MAI_SAMPLE_RATE_176400 = 14,
++      VC4_HDMI_MAI_SAMPLE_RATE_192000 = 15,
++};
++
+ # define VC4_HDMI_RAM_PACKET_ENABLE           BIT(16)
+ /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
diff --git a/target/linux/bcm27xx/patches-5.4/950-0892-drm-vc4-add-iec958-controls-to-vc4_hdmi.patch b/target/linux/bcm27xx/patches-5.4/950-0892-drm-vc4-add-iec958-controls-to-vc4_hdmi.patch
new file mode 100644 (file)
index 0000000..bc5aaca
--- /dev/null
@@ -0,0 +1,119 @@
+From 209a350d81cded4ac83c31088d9e941c6497eb0e Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Tue, 17 Mar 2020 12:12:22 +0100
+Subject: [PATCH] drm/vc4: add iec958 controls to vc4_hdmi
+
+Although vc4 get an IEC958 formatted stream passed in from userspace
+the driver needs the info from the channel status bits to properly
+set up the hardware, eg for HBR passthrough.
+
+Add iec958 controls so the channel status bits can be passed in
+from userspace.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 60 ++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_hdmi.h |  2 ++
+ 2 files changed, 62 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -43,6 +43,7 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/rational.h>
+ #include <linux/reset.h>
++#include <sound/asoundef.h>
+ #include <sound/dmaengine_pcm.h>
+ #include <sound/pcm_drm_eld.h>
+ #include <sound/pcm_params.h>
+@@ -1106,6 +1107,47 @@ static int vc4_hdmi_audio_eld_ctl_get(st
+       return 0;
+ }
++static int vc4_spdif_info(struct snd_kcontrol *kcontrol,
++                        struct snd_ctl_elem_info *uinfo)
++{
++      uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
++      uinfo->count = 1;
++      return 0;
++}
++
++static int vc4_spdif_playback_get(struct snd_kcontrol *kcontrol,
++                                struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
++      struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
++
++      memcpy(ucontrol->value.iec958.status, vc4_hdmi->audio.iec_status,
++              sizeof(vc4_hdmi->audio.iec_status));
++
++      return 0;
++}
++
++static int vc4_spdif_playback_put(struct snd_kcontrol *kcontrol,
++                                struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
++      struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
++
++      memcpy(vc4_hdmi->audio.iec_status, ucontrol->value.iec958.status,
++              sizeof(vc4_hdmi->audio.iec_status));
++
++      return 0;
++}
++
++static int vc4_spdif_mask_get(struct snd_kcontrol *kcontrol,
++                            struct snd_ctl_elem_value *ucontrol)
++{
++      memset(ucontrol->value.iec958.status, 0xff,
++              FIELD_SIZEOF(struct vc4_hdmi_audio, iec_status));
++
++      return 0;
++}
++
+ static const struct snd_kcontrol_new vc4_hdmi_audio_controls[] = {
+       {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ |
+@@ -1115,6 +1157,19 @@ static const struct snd_kcontrol_new vc4
+               .info = vc4_hdmi_audio_eld_ctl_info,
+               .get = vc4_hdmi_audio_eld_ctl_get,
+       },
++      {
++              .iface =   SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name =    SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
++              .info =    vc4_spdif_info,
++              .get =     vc4_spdif_playback_get,
++              .put =     vc4_spdif_playback_put,
++      },
++      {
++              .iface =   SNDRV_CTL_ELEM_IFACE_MIXER,
++              .name =    SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
++              .info =    vc4_spdif_info,
++              .get =     vc4_spdif_mask_get,
++      },
+ };
+ static const struct snd_soc_dapm_widget vc4_hdmi_audio_widgets[] = {
+@@ -1235,6 +1290,11 @@ static int vc4_hdmi_audio_init(struct vc
+       vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       vc4_hdmi->audio.dma_data.maxburst = 2;
++      vc4_hdmi->audio.iec_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
++      vc4_hdmi->audio.iec_status[1] =
++              IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER;
++      vc4_hdmi->audio.iec_status[3] = IEC958_AES3_CON_FS_48000;
++
+       ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
+       if (ret) {
+               dev_err(dev, "Could not register PCM component: %d\n", ret);
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
+@@ -115,6 +115,8 @@ struct vc4_hdmi_audio {
+       struct snd_pcm_substream *substream;
+       bool streaming;
++
++      unsigned char iec_status[4];
+ };
+ /* General HDMI hardware state. */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0893-drm-vc4-move-setup-from-hw_params-to-prepare.patch b/target/linux/bcm27xx/patches-5.4/950-0893-drm-vc4-move-setup-from-hw_params-to-prepare.patch
new file mode 100644 (file)
index 0000000..1e63b34
--- /dev/null
@@ -0,0 +1,56 @@
+From 18b1ff043d713b6b3669a8746062f2faeb6c3557 Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Thu, 19 Mar 2020 20:00:35 +0100
+Subject: [PATCH] drm/vc4: move setup from hw_params to prepare
+
+Configuring HDMI audio registers in prepare allows us to take
+IEC958 bits into account which are set by the alsa hook after
+the hw_params call.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -958,8 +958,7 @@ static int sample_rate_to_mai_fmt(int sa
+ }
+ /* HDMI audio codec callbacks */
+-static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+-                                  struct snd_pcm_hw_params *params,
++static int vc4_hdmi_audio_prepare(struct snd_pcm_substream *substream,
+                                   struct snd_soc_dai *dai)
+ {
+       struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+@@ -972,12 +971,15 @@ static int vc4_hdmi_audio_hw_params(stru
+       if (substream != vc4_hdmi->audio.substream)
+               return -EINVAL;
+-      dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
+-              params_rate(params), params_width(params),
+-              params_channels(params));
++      dev_dbg(dev, "%s: %u Hz, %d bit, %d channels AES0=%02x\n",
++              __func__,
++              substream->runtime->rate,
++              snd_pcm_format_width(substream->runtime->format),
++              substream->runtime->channels,
++              vc4_hdmi->audio.iec_status[0]);
+-      vc4_hdmi->audio.channels = params_channels(params);
+-      vc4_hdmi->audio.samplerate = params_rate(params);
++      vc4_hdmi->audio.channels = substream->runtime->channels;
++      vc4_hdmi->audio.samplerate = substream->runtime->rate;
+       HDMI_WRITE(HDMI_MAI_CTL,
+                VC4_HD_MAI_CTL_RESET |
+@@ -1196,7 +1198,7 @@ static const struct snd_soc_component_dr
+ static const struct snd_soc_dai_ops vc4_hdmi_audio_dai_ops = {
+       .startup = vc4_hdmi_audio_startup,
+       .shutdown = vc4_hdmi_audio_shutdown,
+-      .hw_params = vc4_hdmi_audio_hw_params,
++      .prepare = vc4_hdmi_audio_prepare,
+       .set_fmt = vc4_hdmi_audio_set_fmt,
+       .trigger = vc4_hdmi_audio_trigger,
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0894-drm-vc4-enable-HBR-MAI-format-on-HBR-streams.patch b/target/linux/bcm27xx/patches-5.4/950-0894-drm-vc4-enable-HBR-MAI-format-on-HBR-streams.patch
new file mode 100644 (file)
index 0000000..823e9eb
--- /dev/null
@@ -0,0 +1,25 @@
+From 52beca6270b034cce84a738c71d36ffff7088389 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Fri, 10 Jul 2020 11:51:16 +0100
+Subject: [PATCH] drm/vc4: enable HBR MAI format on HBR streams
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -991,7 +991,11 @@ static int vc4_hdmi_audio_prepare(struct
+       vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
+       mai_sample_rate = sample_rate_to_mai_fmt(vc4_hdmi->audio.samplerate);
+-      mai_audio_format = VC4_HDMI_MAI_FORMAT_PCM;
++      if (vc4_hdmi->audio.iec_status[0] & IEC958_AES0_NONAUDIO &&
++              vc4_hdmi->audio.channels == 8)
++              mai_audio_format = VC4_HDMI_MAI_FORMAT_HBR;
++      else
++              mai_audio_format = VC4_HDMI_MAI_FORMAT_PCM;
+       HDMI_WRITE(HDMI_MAI_FMT,
+               VC4_SET_FIELD(mai_sample_rate, VC4_HDMI_MAI_FORMAT_SAMPLE_RATE) |
+               VC4_SET_FIELD(mai_audio_format, VC4_HDMI_MAI_FORMAT_AUDIO_FORMAT));
diff --git a/target/linux/bcm27xx/patches-5.4/950-0895-vc4_hdmi-Remove-firmware-logic-for-MAI-threshold-set.patch b/target/linux/bcm27xx/patches-5.4/950-0895-vc4_hdmi-Remove-firmware-logic-for-MAI-threshold-set.patch
new file mode 100644 (file)
index 0000000..e08ceca
--- /dev/null
@@ -0,0 +1,47 @@
+From 5f22fca663178a49bbb72058ea9225d35b3d155d Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Thu, 25 Jun 2020 18:48:40 +0100
+Subject: [PATCH] vc4_hdmi: Remove firmware logic for MAI threshold
+ setting
+
+This was a workaround for bugs in hardware on earlier Pi models
+and wasn't totally successful.
+
+It makes audio quality worse on a Pi4 at the higher sample rates
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 22 ++++++----------------
+ 1 file changed, 6 insertions(+), 16 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -1010,22 +1010,12 @@ static int vc4_hdmi_audio_prepare(struct
+       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(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));
+       HDMI_WRITE(HDMI_MAI_CONFIG,
+                  VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
diff --git a/target/linux/bcm27xx/patches-5.4/950-0896-vc_hdmi-Set-VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE.patch b/target/linux/bcm27xx/patches-5.4/950-0896-vc_hdmi-Set-VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE.patch
new file mode 100644 (file)
index 0000000..6fca81a
--- /dev/null
@@ -0,0 +1,24 @@
+From 203c14fa37c25a7d92c4f433ae918c6a7ce4f4db Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Tue, 30 Jun 2020 11:23:49 +0100
+Subject: [PATCH] vc_hdmi: Set VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE
+
+Without this bit set, HDMI_MAI_FORMAT doesn't pick up
+the format and samplerate from DVP_CFG_MAI0_FMT and you
+can't get HDMI_HDMI_13_AUDIO_STATUS_1 to indicate HBR mode
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -1019,6 +1019,7 @@ static int vc4_hdmi_audio_prepare(struct
+       HDMI_WRITE(HDMI_MAI_CONFIG,
+                  VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
++                 VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE |
+                  VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
+       channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0897-dts-Enable-NO_WAIT_RESP-for-hdmi-audio-dma.patch b/target/linux/bcm27xx/patches-5.4/950-0897-dts-Enable-NO_WAIT_RESP-for-hdmi-audio-dma.patch
new file mode 100644 (file)
index 0000000..7e84dc4
--- /dev/null
@@ -0,0 +1,45 @@
+From 2318f056a6c740f66fdeb6b9f47cea319dcdeb20 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Thu, 2 Jul 2020 19:36:08 +0100
+Subject: [PATCH] dts: Enable NO_WAIT_RESP for hdmi audio dma
+
+Without this set, DVP_CFG_MAI0_CTL indicates occasional
+DLATE errors when configured to 8 channel 192kHz
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi    | 4 ++--
+ arch/arm/boot/dts/bcm2835-common.dtsi | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -74,7 +74,7 @@
+                       clock-names = "hdmi";
+                       resets = <&dvp 0>;
+                       ddc = <&ddc0>;
+-                      dmas = <&dma 10>;
++                      dmas = <&dma (10|(1<<27))>;
+                       dma-names = "audio-rx";
+                       interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+@@ -114,7 +114,7 @@
+                       clocks = <&firmware_clocks 13>;
+                       clock-names = "hdmi";
+                       resets = <&dvp 1>;
+-                      dmas = <&dma 17>;
++                      dmas = <&dma (17|(1<<27))>;
+                       dma-names = "audio-rx";
+                       interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+--- a/arch/arm/boot/dts/bcm2835-common.dtsi
++++ b/arch/arm/boot/dts/bcm2835-common.dtsi
+@@ -117,7 +117,7 @@
+                       clocks = <&clocks BCM2835_PLLH_PIX>,
+                                <&clocks BCM2835_CLOCK_HSM>;
+                       clock-names = "pixel", "hdmi";
+-                      dmas = <&dma 17>;
++                      dmas = <&dma (17|(1<<27))>;
+                       dma-names = "audio-rx";
+                       status = "disabled";
+               };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0898-SQUASH-dts-Further-simplify-firmware-clocks.patch b/target/linux/bcm27xx/patches-5.4/950-0898-SQUASH-dts-Further-simplify-firmware-clocks.patch
new file mode 100644 (file)
index 0000000..eea0166
--- /dev/null
@@ -0,0 +1,69 @@
+From af629960be92b1548d0b3c15b6e082930403fbae Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 10 Jul 2020 16:57:43 +0100
+Subject: [PATCH] SQUASH: dts: Further simplify firmware clocks
+
+All Pi platforms will use the firmware clocks driver, so declare it in
+the most common place - bcm2835-rpi.dtsi.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2709-rpi.dtsi | 7 -------
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 7 -------
+ arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 +++++
+ arch/arm/boot/dts/bcm2836-rpi.dtsi | 7 -------
+ 4 files changed, 5 insertions(+), 21 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2709-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2709-rpi.dtsi
+@@ -3,10 +3,3 @@
+ &vchiq {
+       compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
+ };
+-
+-&firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-};
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -309,10 +309,3 @@
+ &hvs {
+       clocks = <&firmware_clocks 4>;
+ };
+-
+-&firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-};
+--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
+@@ -16,6 +16,11 @@
+                       compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+                       mboxes = <&mailbox>;
+                       dma-ranges;
++
++                      firmware_clocks: clocks {
++                              compatible = "raspberrypi,firmware-clocks";
++                              #clock-cells = <1>;
++                      };
+               };
+               power: power {
+--- a/arch/arm/boot/dts/bcm2836-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
+@@ -4,10 +4,3 @@
+ &vchiq {
+       compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
+ };
+-
+-&firmware {
+-      firmware_clocks: clocks {
+-              compatible = "raspberrypi,firmware-clocks";
+-              #clock-cells = <1>;
+-      };
+-};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0899-media-bcm2835-unicam-Set-VPU-min-clock-freq-to-250Mh.patch b/target/linux/bcm27xx/patches-5.4/950-0899-media-bcm2835-unicam-Set-VPU-min-clock-freq-to-250Mh.patch
new file mode 100644 (file)
index 0000000..788606c
--- /dev/null
@@ -0,0 +1,154 @@
+From 09c1533f7f5dabd79aa2018083d1b71d26cd7eda Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Mon, 11 May 2020 13:02:22 +0100
+Subject: [PATCH] media: bcm2835: unicam: Set VPU min clock freq to
+ 250Mhz.
+
+When streaming with Unicam, the VPU must have a clock frequency of at
+least 250Mhz.  Otherwise, the input fifos could overrun, causing
+image corruption.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm270x.dtsi                | 10 ++--
+ .../media/platform/bcm2835/bcm2835-unicam.c   | 49 +++++++++++++++++--
+ 2 files changed, 50 insertions(+), 9 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -88,8 +88,9 @@
+                       reg = <0x7e800000 0x800>,
+                             <0x7e802000 0x4>;
+                       interrupts = <2 6>;
+-                      clocks = <&clocks BCM2835_CLOCK_CAM0>;
+-                      clock-names = "lp";
++                      clocks = <&clocks BCM2835_CLOCK_CAM0>,
++                               <&firmware_clocks 4>;
++                      clock-names = "lp", "vpu";
+                       power-domains = <&power RPI_POWER_DOMAIN_UNICAM0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+@@ -102,8 +103,9 @@
+                       reg = <0x7e801000 0x800>,
+                             <0x7e802004 0x4>;
+                       interrupts = <2 7>;
+-                      clocks = <&clocks BCM2835_CLOCK_CAM1>;
+-                      clock-names = "lp";
++                      clocks = <&clocks BCM2835_CLOCK_CAM1>,
++                               <&firmware_clocks 4>;
++                      clock-names = "lp", "vpu";
+                       power-domains = <&power RPI_POWER_DOMAIN_UNICAM1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -89,6 +89,11 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
+               v4l2_err(&(dev)->v4l2_dev, fmt, ##arg)
+ /*
++ * Unicam must request a minimum of 250Mhz from the VPU clock.
++ * Otherwise the input FIFOs overrun and cause image corruption.
++ */
++#define MIN_VPU_CLOCK_RATE (250 * 1000 * 1000)
++/*
+  * To protect against a dodgy sensor driver never returning an error from
+  * enum_mbus_code, set a maximum index value to be used.
+  */
+@@ -417,8 +422,10 @@ struct unicam_device {
+       void __iomem *base;
+       /* clock gating base address */
+       void __iomem *clk_gate_base;
+-      /* clock handle */
++      /* lp clock handle */
+       struct clk *clock;
++      /* vpu clock handle */
++      struct clk *vpu_clock;
+       /* V4l2 device */
+       struct v4l2_device v4l2_dev;
+       struct media_device mdev;
+@@ -1674,16 +1681,28 @@ static int unicam_start_streaming(struct
+       unicam_dbg(1, dev, "Running with %u data lanes\n",
+                  dev->active_data_lanes);
+-      ret = clk_set_rate(dev->clock, 100 * 1000 * 1000);
++      ret = clk_set_min_rate(dev->vpu_clock, MIN_VPU_CLOCK_RATE);
++      if (ret) {
++              unicam_err(dev, "failed to set up VPU clock\n");
++              goto err_pm_put;
++      }
++
++      ret = clk_prepare_enable(dev->vpu_clock);
+       if (ret) {
+-              unicam_err(dev, "failed to set up clock\n");
++              unicam_err(dev, "Failed to enable VPU clock: %d\n", ret);
+               goto err_pm_put;
+       }
++      ret = clk_set_rate(dev->clock, 100 * 1000 * 1000);
++      if (ret) {
++              unicam_err(dev, "failed to set up CSI clock\n");
++              goto err_vpu_clock;
++      }
++
+       ret = clk_prepare_enable(dev->clock);
+       if (ret) {
+               unicam_err(dev, "Failed to enable CSI clock: %d\n", ret);
+-              goto err_pm_put;
++              goto err_vpu_clock;
+       }
+       for (i = 0; i < ARRAY_SIZE(dev->node); i++) {
+@@ -1717,6 +1736,11 @@ static int unicam_start_streaming(struct
+ err_disable_unicam:
+       unicam_disable(dev);
+       clk_disable_unprepare(dev->clock);
++err_vpu_clock:
++      ret = clk_set_min_rate(dev->vpu_clock, 0);
++      if (ret)
++              unicam_err(dev, "failed to reset the VPU clock\n");
++      clk_disable_unprepare(dev->vpu_clock);
+ err_pm_put:
+       unicam_runtime_put(dev);
+ err_streaming:
+@@ -1734,6 +1758,8 @@ static void unicam_stop_streaming(struct
+       node->streaming = false;
+       if (node->pad_id == IMAGE_PAD) {
++              int ret;
++
+               /*
+                * Stop streaming the sensor and disable the peripheral.
+                * We cannot continue streaming embedded data with the
+@@ -1743,6 +1769,12 @@ static void unicam_stop_streaming(struct
+                       unicam_err(dev, "stream off failed in subdev\n");
+               unicam_disable(dev);
++
++              ret = clk_set_min_rate(dev->vpu_clock, 0);
++              if (ret)
++                      unicam_err(dev, "failed to reset the min VPU clock\n");
++
++              clk_disable_unprepare(dev->vpu_clock);
+               clk_disable_unprepare(dev->clock);
+               unicam_runtime_put(dev);
+@@ -2742,11 +2774,18 @@ static int unicam_probe(struct platform_
+       unicam->clock = devm_clk_get(&pdev->dev, "lp");
+       if (IS_ERR(unicam->clock)) {
+-              unicam_err(unicam, "Failed to get clock\n");
++              unicam_err(unicam, "Failed to get lp clock\n");
+               ret = PTR_ERR(unicam->clock);
+               goto err_unicam_put;
+       }
++      unicam->vpu_clock = devm_clk_get(&pdev->dev, "vpu");
++      if (IS_ERR(unicam->vpu_clock)) {
++              unicam_err(unicam, "Failed to get vpu clock\n");
++              ret = PTR_ERR(unicam->vpu_clock);
++              goto err_unicam_put;
++      }
++
+       ret = platform_get_irq(pdev, 0);
+       if (ret <= 0) {
+               dev_err(&pdev->dev, "No IRQ resource\n");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0900-dt-bindings-bcm2835-unicam-Update-documentation-with.patch b/target/linux/bcm27xx/patches-5.4/950-0900-dt-bindings-bcm2835-unicam-Update-documentation-with.patch
new file mode 100644 (file)
index 0000000..c8b53d6
--- /dev/null
@@ -0,0 +1,38 @@
+From f747c5b5f35490ff177b8327ff1f7299f7d0bf4a Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Mon, 11 May 2020 13:06:27 +0100
+Subject: [PATCH] dt-bindings: bcm2835-unicam: Update documentation
+ with new clock params
+
+Update the documentation to reflect the new "VPU" clock needed
+by the bcm2835-unicam driver.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ .../devicetree/bindings/media/bcm2835-unicam.txt          | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/Documentation/devicetree/bindings/media/bcm2835-unicam.txt
++++ b/Documentation/devicetree/bindings/media/bcm2835-unicam.txt
+@@ -20,7 +20,7 @@ Required properties:
+ - interrupts  : should contain the IRQ line for this Unicam instance.
+ - clocks      : list of clock specifiers, corresponding to entries in
+                 clock-names property.
+-- clock-names : must contain an "lp" entry, matching entries in the
++- clock-names : must contain "lp" and "vpu" entries, matching entries in the
+                 clocks property.
+ Unicam supports a single port node. It should contain one 'port' child node
+@@ -46,9 +46,9 @@ Example:
+               reg = <0x7e801000 0x800>,
+                     <0x7e802004 0x4>;
+               interrupts = <2 7>;
+-              clocks = <&clocks BCM2835_CLOCK_CAM1>;
+-              clock-names = "lp";
+-
++              clocks = <&clocks BCM2835_CLOCK_CAM1>,
++                       <&firmware_clocks 4>;
++              clock-names = "lp", "vpu";
+               port {
+                       csi1_ep: endpoint {
+                               remote-endpoint = <&tc358743_0>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0901-correct-SND_SOC_DAILINK_DEFS.patch b/target/linux/bcm27xx/patches-5.4/950-0901-correct-SND_SOC_DAILINK_DEFS.patch
new file mode 100644 (file)
index 0000000..6823283
--- /dev/null
@@ -0,0 +1,21 @@
+From b27a6e98851f8889f8d9059bfebb91014ac7b057 Mon Sep 17 00:00:00 2001
+From: AMuszkat <ariel.muszkat@gmail.com>
+Date: Tue, 14 Jul 2020 17:51:03 +0200
+Subject: [PATCH] correct SND_SOC_DAILINK_DEFS
+
+Signed-off-by: AMuszkat <ariel.muszkat@gmail.com>
+---
+ sound/soc/bcm/rpi-simple-soundcard.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/bcm/rpi-simple-soundcard.c
++++ b/sound/soc/bcm/rpi-simple-soundcard.c
+@@ -235,7 +235,7 @@ static struct snd_rpi_simple_drvdata drv
+ SND_SOC_DAILINK_DEFS(merus_amp,
+       DAILINK_COMP_ARRAY(COMP_EMPTY()),
+-      DAILINK_COMP_ARRAY(COMP_CODEC("ma120x0p-amp", "ma120x0p.1-0020")),
++      DAILINK_COMP_ARRAY(COMP_CODEC("ma120x0p.1-0020","ma120x0p-amp")),
+       DAILINK_COMP_ARRAY(COMP_EMPTY()));
+ static struct snd_soc_dai_link snd_merus_amp_dai[] = {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0902-media-dt-bindings-video-interfaces-Document-orientat.patch b/target/linux/bcm27xx/patches-5.4/950-0902-media-dt-bindings-video-interfaces-Document-orientat.patch
new file mode 100644 (file)
index 0000000..de2fd15
--- /dev/null
@@ -0,0 +1,43 @@
+From cc7d8104a44cf0ad67081f9ad0efd0e260a2379b Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:44 +0200
+Subject: [PATCH] media: dt-bindings: video-interfaces: Document
+ 'orientation' property
+
+Add the 'orientation' device property, used to specify the device mounting
+position. The property is particularly meaningful for mobile devices
+with a well defined usage orientation.
+
+Reviewed-by: Rob Herring <robh@kernel.org>
+Acked-by: Tomasz Figa <tfiga@chromium.org>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit cabc918e5b877ed547e5b6463f5ea6e3ac4edbb3 upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ .../devicetree/bindings/media/video-interfaces.txt    | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/Documentation/devicetree/bindings/media/video-interfaces.txt
++++ b/Documentation/devicetree/bindings/media/video-interfaces.txt
+@@ -89,6 +89,17 @@ Optional properties
+   but a number of degrees counter clockwise. Typical values are 0 and 180
+   (upside down).
++- orientation: The orientation of a device (typically an image sensor or a flash
++  LED) describing its mounting position relative to the usage orientation of the
++  system where the device is installed on.
++  Possible values are:
++  0 - Front. The device is mounted on the front facing side of the system.
++  For mobile devices such as smartphones, tablets and laptops the front side is
++  the user facing side.
++  1 - Back. The device is mounted on the back side of the system, which is
++  defined as the opposite side of the front facing one.
++  2 - External. The device is not attached directly to the system but is
++  attached in a way that allows it to move freely.
+ Optional endpoint properties
+ ----------------------------
diff --git a/target/linux/bcm27xx/patches-5.4/950-0903-media-dt-bindings-video-interface-Replace-rotation-d.patch b/target/linux/bcm27xx/patches-5.4/950-0903-media-dt-bindings-video-interface-Replace-rotation-d.patch
new file mode 100644 (file)
index 0000000..a070c2a
--- /dev/null
@@ -0,0 +1,390 @@
+From 1af1c75a6965dd975d40e904e921d9f07395ffcb Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:45 +0200
+Subject: [PATCH] media: dt-bindings: video-interface: Replace
+ 'rotation' description
+
+Replace the 'rotation' property description by providing a definition
+relative to the camera sensor pixel array coordinate system and the
+captured scene.
+
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit 915bd31ce9ed328535e5ecf3ca730c5764ec1a38 upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ .../bindings/media/video-interfaces.txt       | 359 +++++++++++++++++-
+ 1 file changed, 356 insertions(+), 3 deletions(-)
+
+--- a/Documentation/devicetree/bindings/media/video-interfaces.txt
++++ b/Documentation/devicetree/bindings/media/video-interfaces.txt
+@@ -85,9 +85,362 @@ Optional properties
+ - lens-focus: A phandle to the node of the focus lens controller.
+-- rotation: The device, typically an image sensor, is not mounted upright,
+-  but a number of degrees counter clockwise. Typical values are 0 and 180
+-  (upside down).
++- rotation: The camera rotation is expressed as the angular difference in
++  degrees between two reference systems, one relative to the camera module, and
++  one defined on the external world scene to be captured when projected on the
++  image sensor pixel array.
++
++  A camera sensor has a 2-dimensional reference system 'Rc' defined by
++  its pixel array read-out order. The origin is set to the first pixel
++  being read out, the X-axis points along the column read-out direction
++  towards the last columns, and the Y-axis along the row read-out
++  direction towards the last row.
++
++  A typical example for a sensor with a 2592x1944 pixel array matrix
++  observed from the front is:
++
++              2591       X-axis          0
++                <------------------------+ 0
++                .......... ... ..........!
++                .......... ... ..........! Y-axis
++                           ...           !
++                .......... ... ..........!
++                .......... ... ..........! 1943
++                                         V
++
++  The external world scene reference system 'Rs' is a 2-dimensional
++  reference system on the focal plane of the camera module. The origin is
++  placed on the top-left corner of the visible scene, the X-axis points
++  towards the right, and the Y-axis points towards the bottom of the
++  scene. The top, bottom, left and right directions are intentionally not
++  defined and depend on the environment in which the camera is used.
++
++  A typical example of a (very common) picture of a shark swimming from
++  left to right, as seen from the camera, is:
++
++               0               X-axis
++             0 +------------------------------------->
++               !
++               !
++               !
++               !           |\____)\___
++               !           ) _____  __`<
++               !           |/     )/
++               !
++               !
++               !
++               V
++             Y-axis
++
++  with the reference system 'Rs' placed on the camera focal plane:
++
++                                  ¸.·˙!
++                              ¸.·˙    !
++                  _       ¸.·˙        !
++               +-/ \-+¸.·˙            !
++               | (o) |                ! Camera focal plane
++               +-----+˙·.¸            !
++                          ˙·.¸        !
++                              ˙·.¸    !
++                                  ˙·.¸!
++
++  When projected on the sensor's pixel array, the image and the associated
++  reference system 'Rs' are typically (but not always) inverted, due to
++  the camera module's lens optical inversion effect.
++
++  Assuming the above represented scene of the swimming shark, the lens
++  inversion projects the scene and its reference system onto the sensor
++  pixel array, seen from the front of the camera sensor, as follows:
++
++            Y-axis
++               ^
++               !
++               !
++               !
++               !            |\_____)\__
++               !            ) ____  ___.<
++               !            |/    )/
++               !
++               !
++               !
++             0 +------------------------------------->
++               0               X-axis
++
++  Note the shark being upside-down.
++
++  The resulting projected reference system is named 'Rp'.
++
++  The camera rotation property is then defined as the angular difference
++  in the counter-clockwise direction between the camera reference system
++  'Rc' and the projected scene reference system 'Rp'. It is expressed in
++  degrees as a number in the range [0, 360[.
++
++  Examples
++
++  0 degrees camera rotation:
++
++
++                    Y-Rp
++                     ^
++              Y-Rc   !
++               ^     !
++               !     !
++               !     !
++               !     !
++               !     !
++               !     !
++               !     !
++               !     !
++               !   0 +------------------------------------->
++               !     0               X-Rp
++             0 +------------------------------------->
++               0               X-Rc
++
++
++                                X-Rc                0
++               <------------------------------------+ 0
++                           X-Rp                 0   !
++           <------------------------------------+ 0 !
++                                                !   !
++                                                !   !
++                                                !   !
++                                                !   !
++                                                !   !
++                                                !   !
++                                                !   !
++                                                !   V
++                                                !  Y-Rc
++                                                V
++                                               Y-Rp
++
++  90 degrees camera rotation:
++
++               0        Y-Rc
++             0 +-------------------->
++               !   Y-Rp
++               !    ^
++               !    !
++               !    !
++               !    !
++               !    !
++               !    !
++               !    !
++               !    !
++               !    !
++               !    !
++               !  0 +------------------------------------->
++               !    0              X-Rp
++               !
++               !
++               !
++               !
++               V
++              X-Rc
++
++  180 degrees camera rotation:
++
++                                            0
++       <------------------------------------+ 0
++                        X-Rc                !
++              Y-Rp                          !
++               ^                            !
++               !                            !
++               !                            !
++               !                            !
++               !                            !
++               !                            !
++               !                            !
++               !                            V
++               !                           Y-Rc
++             0 +------------------------------------->
++               0              X-Rp
++
++  270 degrees camera rotation:
++
++               0        Y-Rc
++             0 +-------------------->
++               !                                        0
++               !    <-----------------------------------+ 0
++               !                    X-Rp                !
++               !                                        !
++               !                                        !
++               !                                        !
++               !                                        !
++               !                                        !
++               !                                        !
++               !                                        !
++               !                                        !
++               !                                        V
++               !                                       Y-Rp
++               !
++               !
++               !
++               !
++               V
++              X-Rc
++
++
++  Example one - Webcam
++
++  A camera module installed on the user facing part of a laptop screen
++  casing used for video calls. The captured images are meant to be
++  displayed in landscape mode (width > height) on the laptop screen.
++
++  The camera is typically mounted upside-down to compensate the lens
++  optical inversion effect:
++
++                    Y-Rp
++              Y-Rc   ^
++               ^     !
++               !     !
++               !     !       |\_____)\__
++               !     !       ) ____  ___.<
++               !     !       |/    )/
++               !     !
++               !     !
++               !     !
++               !   0 +------------------------------------->
++               !     0           X-Rp
++             0 +------------------------------------->
++               0            X-Rc
++
++  The two reference systems are aligned, the resulting camera rotation is
++  0 degrees, no rotation correction needs to be applied to the resulting
++  image once captured to memory buffers to correctly display it to users:
++
++               +--------------------------------------+
++               !                                      !
++               !                                      !
++               !                                      !
++               !             |\____)\___              !
++               !             ) _____  __`<            !
++               !             |/     )/                !
++               !                                      !
++               !                                      !
++               !                                      !
++               +--------------------------------------+
++
++  If the camera sensor is not mounted upside-down to compensate for the
++  lens optical inversion, the two reference systems will not be aligned,
++  with 'Rp' being rotated 180 degrees relatively to 'Rc':
++
++
++                        X-Rc                0
++       <------------------------------------+ 0
++                                            !
++              Y-Rp                          !
++               ^                            !
++               !                            !
++               !       |\_____)\__          !
++               !       ) ____  ___.<        !
++               !       |/    )/             !
++               !                            !
++               !                            !
++               !                            V
++               !                           Y-Rc
++             0 +------------------------------------->
++               0            X-Rp
++
++  The image once captured to memory will then be rotated by 180 degrees:
++
++               +--------------------------------------+
++               !                                      !
++               !                                      !
++               !                                      !
++               !              __/(_____/|             !
++               !            >.___  ____ (             !
++               !                 \(    \|             !
++               !                                      !
++               !                                      !
++               !                                      !
++               +--------------------------------------+
++
++  A software rotation correction of 180 degrees should be applied to
++  correctly display the image:
++
++               +--------------------------------------+
++               !                                      !
++               !                                      !
++               !                                      !
++               !             |\____)\___              !
++               !             ) _____  __`<            !
++               !             |/     )/                !
++               !                                      !
++               !                                      !
++               !                                      !
++               +--------------------------------------+
++
++  Example two - Phone camera
++
++  A camera installed on the back side of a mobile device facing away from
++  the user. The captured images are meant to be displayed in portrait mode
++  (height > width) to match the device screen orientation and the device
++  usage orientation used when taking the picture.
++
++  The camera sensor is typically mounted with its pixel array longer side
++  aligned to the device longer side, upside-down mounted to compensate for
++  the lens optical inversion effect:
++
++               0        Y-Rc
++             0 +-------------------->
++               !   Y-Rp
++               !    ^
++               !    !
++               !    !
++               !    !
++               !    !            |\_____)\__
++               !    !            ) ____  ___.<
++               !    !            |/    )/
++               !    !
++               !    !
++               !    !
++               !  0 +------------------------------------->
++               !    0                X-Rp
++               !
++               !
++               !
++               !
++               V
++              X-Rc
++
++  The two reference systems are not aligned and the 'Rp' reference
++  system is rotated by 90 degrees in the counter-clockwise direction
++  relatively to the 'Rc' reference system.
++
++  The image once captured to memory will be rotated:
++
++               +-------------------------------------+
++               |                 _ _                 |
++               |                \   /                |
++               |                 | |                 |
++               |                 | |                 |
++               |                 |  >                |
++               |                <  |                 |
++               |                 | |                 |
++               |                   .                 |
++               |                  V                  |
++               +-------------------------------------+
++
++  A correction of 90 degrees in counter-clockwise direction has to be
++  applied to correctly display the image in portrait mode on the device
++  screen:
++
++                        +--------------------+
++                        |                    |
++                        |                    |
++                        |                    |
++                        |                    |
++                        |                    |
++                        |                    |
++                        |   |\____)\___      |
++                        |   ) _____  __`<    |
++                        |   |/     )/        |
++                        |                    |
++                        |                    |
++                        |                    |
++                        |                    |
++                        |                    |
++                        +--------------------+
+ - orientation: The orientation of a device (typically an image sensor or a flash
+   LED) describing its mounting position relative to the usage orientation of the
diff --git a/target/linux/bcm27xx/patches-5.4/950-0904-media-v4l2-ctrl-Document-V4L2_CID_CAMERA_ORIENTATION.patch b/target/linux/bcm27xx/patches-5.4/950-0904-media-v4l2-ctrl-Document-V4L2_CID_CAMERA_ORIENTATION.patch
new file mode 100644 (file)
index 0000000..9516e65
--- /dev/null
@@ -0,0 +1,61 @@
+From 16a7ef36055e414560143ebcb95113f9513ca49d Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:46 +0200
+Subject: [PATCH] media: v4l2-ctrl: Document
+ V4L2_CID_CAMERA_ORIENTATION
+
+Add documentation for the V4L2_CID_CAMERA_ORIENTATION camera
+control. The newly added read-only control reports the camera device
+orientation relative to the usage orientation of the system the camera
+is installed on.
+
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit 9397a83f40183eeafd5c787af2240ed0d6b26daa upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ .../media/uapi/v4l/ext-ctrls-camera.rst       | 30 +++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+--- a/Documentation/media/uapi/v4l/ext-ctrls-camera.rst
++++ b/Documentation/media/uapi/v4l/ext-ctrls-camera.rst
+@@ -510,6 +510,36 @@ enum v4l2_scene_mode -
+     value down. A value of zero stops the motion if one is in progress
+     and has no effect otherwise.
++``V4L2_CID_CAMERA_ORIENTATION (menu)``
++    This read-only control describes the camera orientation by reporting its
++    mounting position on the device where the camera is installed. The control
++    value is constant and not modifiable by software. This control is
++    particularly meaningful for devices which have a well defined orientation,
++    such as phones, laptops and portable devices since the control is expressed
++    as a position relative to the device's intended usage orientation. For
++    example, a camera installed on the user-facing side of a phone, a tablet or
++    a laptop device is said to be have ``V4L2_CAMERA_ORIENTATION_FRONT``
++    orientation, while a camera installed on the opposite side of the front one
++    is said to be have ``V4L2_CAMERA_ORIENTATION_BACK`` orientation. Camera
++    sensors not directly attached to the device, or attached in a way that
++    allows them to move freely, such as webcams and digital cameras, are said to
++    have the ``V4L2_CAMERA_ORIENTATION_EXTERNAL`` orientation.
++
++
++
++.. flat-table::
++    :header-rows:  0
++    :stub-columns: 0
++
++    * - ``V4L2_CAMERA_ORIENTATION_FRONT``
++      - The camera is oriented towards the user facing side of the device.
++    * - ``V4L2_CAMERA_ORIENTATION_BACK``
++      - The camera is oriented towards the back facing side of the device.
++    * - ``V4L2_CAMERA_ORIENTATION_EXTERNAL``
++      - The camera is not directly attached to the device and is freely movable.
++
++
++
+ .. [#f1]
+    This control may be changed to a menu control in the future, if more
+    options are required.
diff --git a/target/linux/bcm27xx/patches-5.4/950-0905-media-v4l2-ctrl-Document-V4L2_CID_CAMERA_SENSOR_ROTA.patch b/target/linux/bcm27xx/patches-5.4/950-0905-media-v4l2-ctrl-Document-V4L2_CID_CAMERA_SENSOR_ROTA.patch
new file mode 100644 (file)
index 0000000..9be7e6a
--- /dev/null
@@ -0,0 +1,151 @@
+From 00d84a43c7042b55e81d0818b0d1a6e44c6f79b5 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:47 +0200
+Subject: [PATCH] media: v4l2-ctrl: Document
+ V4L2_CID_CAMERA_SENSOR_ROTATION
+
+Add documentation for the V4L2_CID_CAMERA_SENSOR_ROTATION camera
+control. The newly added read-only control reports the rotation
+correction to be applied to images before displaying them to the user.
+
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit 9926c2248740a632b0629fd8c07d0fc361dc15cc upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ .../media/uapi/v4l/ext-ctrls-camera.rst       | 121 ++++++++++++++++++
+ 1 file changed, 121 insertions(+)
+
+--- a/Documentation/media/uapi/v4l/ext-ctrls-camera.rst
++++ b/Documentation/media/uapi/v4l/ext-ctrls-camera.rst
+@@ -540,6 +540,127 @@ enum v4l2_scene_mode -
++``V4L2_CID_CAMERA_SENSOR_ROTATION (integer)``
++    This read-only control describes the rotation correction in degrees in the
++    counter-clockwise direction to be applied to the captured images once
++    captured to memory to compensate for the camera sensor mounting rotation.
++
++    For a precise definition of the sensor mounting rotation refer to the
++    extensive description of the 'rotation' properties in the device tree
++    bindings file 'video-interfaces.txt'.
++
++    A few examples are below reported, using a shark swimming from left to
++    right in front of the user as the example scene to capture. ::
++
++                 0               X-axis
++               0 +------------------------------------->
++                 !
++                 !
++                 !
++                 !           |\____)\___
++                 !           ) _____  __`<
++                 !           |/     )/
++                 !
++                 !
++                 !
++                 V
++               Y-axis
++
++    Example one - Webcam
++
++    Assuming you can bring your laptop with you while swimming with sharks,
++    the camera module of the laptop is installed on the user facing part of a
++    laptop screen casing, and is typically used for video calls. The captured
++    images are meant to be displayed in landscape mode (width > height) on the
++    laptop screen.
++
++    The camera is typically mounted upside-down to compensate the lens optical
++    inversion effect. In this case the value of the
++    V4L2_CID_CAMERA_SENSOR_ROTATION control is 0, no rotation is required to
++    display images correctly to the user.
++
++    If the camera sensor is not mounted upside-down it is required to compensate
++    the lens optical inversion effect and the value of the
++    V4L2_CID_CAMERA_SENSOR_ROTATION control is 180 degrees, as images will
++    result rotated when captured to memory. ::
++
++                 +--------------------------------------+
++                 !                                      !
++                 !                                      !
++                 !                                      !
++                 !              __/(_____/|             !
++                 !            >.___  ____ (             !
++                 !                 \(    \|             !
++                 !                                      !
++                 !                                      !
++                 !                                      !
++                 +--------------------------------------+
++
++    A software rotation correction of 180 degrees has to be applied to correctly
++    display the image on the user screen. ::
++
++                 +--------------------------------------+
++                 !                                      !
++                 !                                      !
++                 !                                      !
++                 !             |\____)\___              !
++                 !             ) _____  __`<            !
++                 !             |/     )/                !
++                 !                                      !
++                 !                                      !
++                 !                                      !
++                 +--------------------------------------+
++
++    Example two - Phone camera
++
++    It is more handy to go and swim with sharks with only your mobile phone
++    with you and take pictures with the camera that is installed on the back
++    side of the device, facing away from the user. The captured images are meant
++    to be displayed in portrait mode (height > width) to match the device screen
++    orientation and the device usage orientation used when taking the picture.
++
++    The camera sensor is typically mounted with its pixel array longer side
++    aligned to the device longer side, upside-down mounted to compensate for
++    the lens optical inversion effect.
++
++    The images once captured to memory will be rotated and the value of the
++    V4L2_CID_CAMERA_SENSOR_ROTATION will report a 90 degree rotation. ::
++
++
++                 +-------------------------------------+
++                 |                 _ _                 |
++                 |                \   /                |
++                 |                 | |                 |
++                 |                 | |                 |
++                 |                 |  >                |
++                 |                <  |                 |
++                 |                 | |                 |
++                 |                   .                 |
++                 |                  V                  |
++                 +-------------------------------------+
++
++    A correction of 90 degrees in counter-clockwise direction has to be
++    applied to correctly display the image in portrait mode on the device
++    screen. ::
++
++                          +--------------------+
++                          |                    |
++                          |                    |
++                          |                    |
++                          |                    |
++                          |                    |
++                          |                    |
++                          |   |\____)\___      |
++                          |   ) _____  __`<    |
++                          |   |/     )/        |
++                          |                    |
++                          |                    |
++                          |                    |
++                          |                    |
++                          |                    |
++                          +--------------------+
++
++
+ .. [#f1]
+    This control may be changed to a menu control in the future, if more
+    options are required.
diff --git a/target/linux/bcm27xx/patches-5.4/950-0906-media-v4l2-ctrls-Add-camera-orientation-and-rotation.patch b/target/linux/bcm27xx/patches-5.4/950-0906-media-v4l2-ctrls-Add-camera-orientation-and-rotation.patch
new file mode 100644 (file)
index 0000000..921b08e
--- /dev/null
@@ -0,0 +1,89 @@
+From d25d713f7bfe272cbeaac90769eb88fee382b2e9 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:48 +0200
+Subject: [PATCH] media: v4l2-ctrls: Add camera orientation and
+ rotation
+
+Add support for the newly defined V4L2_CID_CAMERA_ORIENTATION
+and V4L2_CID_CAMERA_SENSOR_ROTATION read-only controls used to report
+the camera device mounting position and orientation respectively.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit 926645d43fd43622a2b056471a2cf41cc19cbf4c upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/v4l2-core/v4l2-ctrls.c | 13 +++++++++++++
+ include/uapi/linux/v4l2-controls.h   |  7 +++++++
+ 2 files changed, 20 insertions(+)
+
+--- a/drivers/media/v4l2-core/v4l2-ctrls.c
++++ b/drivers/media/v4l2-core/v4l2-ctrls.c
+@@ -577,6 +577,12 @@ const char * const *v4l2_ctrl_get_menu(u
+               "Annex B Start Code",
+               NULL,
+       };
++      static const char * const camera_orientation[] = {
++              "Front",
++              "Back",
++              "External",
++              NULL,
++      };
+       switch (id) {
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+@@ -702,6 +708,8 @@ const char * const *v4l2_ctrl_get_menu(u
+               return hevc_decode_mode;
+       case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:
+               return hevc_start_code;
++      case V4L2_CID_CAMERA_ORIENTATION:
++              return camera_orientation;
+       default:
+               return NULL;
+       }
+@@ -1015,6 +1023,8 @@ const char *v4l2_ctrl_get_name(u32 id)
+       case V4L2_CID_PAN_SPEED:                return "Pan, Speed";
+       case V4L2_CID_TILT_SPEED:               return "Tilt, Speed";
+       case V4L2_CID_UNIT_CELL_SIZE:           return "Unit Cell Size";
++      case V4L2_CID_CAMERA_ORIENTATION:       return "Camera Orientation";
++      case V4L2_CID_CAMERA_SENSOR_ROTATION:   return "Camera Sensor Rotation";
+       /* FM Radio Modulator controls */
+       /* Keep the order of the 'case's the same as in v4l2-controls.h! */
+@@ -1288,6 +1298,7 @@ void v4l2_ctrl_fill(u32 id, const char *
+       case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
+       case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:
+       case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:
++      case V4L2_CID_CAMERA_ORIENTATION:
+               *type = V4L2_CTRL_TYPE_MENU;
+               break;
+       case V4L2_CID_LINK_FREQ:
+@@ -1480,6 +1491,8 @@ void v4l2_ctrl_fill(u32 id, const char *
+       case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
+       case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
+       case V4L2_CID_RDS_RX_MUSIC_SPEECH:
++      case V4L2_CID_CAMERA_ORIENTATION:
++      case V4L2_CID_CAMERA_SENSOR_ROTATION:
+               *flags |= V4L2_CTRL_FLAG_READ_ONLY;
+               break;
+       case V4L2_CID_RF_TUNER_PLL_LOCK:
+--- a/include/uapi/linux/v4l2-controls.h
++++ b/include/uapi/linux/v4l2-controls.h
+@@ -917,6 +917,13 @@ enum v4l2_auto_focus_range {
+ #define V4L2_CID_PAN_SPEED                    (V4L2_CID_CAMERA_CLASS_BASE+32)
+ #define V4L2_CID_TILT_SPEED                   (V4L2_CID_CAMERA_CLASS_BASE+33)
++#define V4L2_CID_CAMERA_ORIENTATION           (V4L2_CID_CAMERA_CLASS_BASE+34)
++#define V4L2_CAMERA_ORIENTATION_FRONT         0
++#define V4L2_CAMERA_ORIENTATION_BACK          1
++#define V4L2_CAMERA_ORIENTATION_EXTERNAL      2
++
++#define V4L2_CID_CAMERA_SENSOR_ROTATION               (V4L2_CID_CAMERA_CLASS_BASE+35)
++
+ /* FM Modulator class control IDs */
+ #define V4L2_CID_FM_TX_CLASS_BASE             (V4L2_CTRL_CLASS_FM_TX | 0x900)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0907-media-v4l2-fwnode-Add-helper-to-parse-device-propert.patch b/target/linux/bcm27xx/patches-5.4/950-0907-media-v4l2-fwnode-Add-helper-to-parse-device-propert.patch
new file mode 100644 (file)
index 0000000..d0d21fc
--- /dev/null
@@ -0,0 +1,138 @@
+From 1cc9056759e1f500de5e401afd4b0acff90cc653 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:49 +0200
+Subject: [PATCH] media: v4l2-fwnode: Add helper to parse device
+ properties
+
+Add an helper function to parse common device properties in the same
+way as v4l2_fwnode_endpoint_parse() parses common endpoint properties.
+
+Parse the 'rotation' and 'orientation' properties from the firmware
+interface.
+
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit 344897ef1d9b33e246b64e255d807ca6c053f349 upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/v4l2-core/v4l2-fwnode.c | 42 ++++++++++++++++++++++++
+ include/media/v4l2-fwnode.h           | 47 +++++++++++++++++++++++++++
+ 2 files changed, 89 insertions(+)
+
+--- a/drivers/media/v4l2-core/v4l2-fwnode.c
++++ b/drivers/media/v4l2-core/v4l2-fwnode.c
+@@ -599,6 +599,48 @@ void v4l2_fwnode_put_link(struct v4l2_fw
+ }
+ EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
++int v4l2_fwnode_device_parse(struct device *dev,
++                           struct v4l2_fwnode_device_properties *props)
++{
++      struct fwnode_handle *fwnode = dev_fwnode(dev);
++      u32 val;
++      int ret;
++
++      memset(props, 0, sizeof(*props));
++
++      props->orientation = V4L2_FWNODE_PROPERTY_UNSET;
++      ret = fwnode_property_read_u32(fwnode, "orientation", &val);
++      if (!ret) {
++              switch (val) {
++              case V4L2_FWNODE_ORIENTATION_FRONT:
++              case V4L2_FWNODE_ORIENTATION_BACK:
++              case V4L2_FWNODE_ORIENTATION_EXTERNAL:
++                      break;
++              default:
++                      dev_warn(dev, "Unsupported device orientation: %u\n", val);
++                      return -EINVAL;
++              }
++
++              props->orientation = val;
++              dev_dbg(dev, "device orientation: %u\n", val);
++      }
++
++      props->rotation = V4L2_FWNODE_PROPERTY_UNSET;
++      ret = fwnode_property_read_u32(fwnode, "rotation", &val);
++      if (!ret) {
++              if (val >= 360) {
++                      dev_warn(dev, "Unsupported device rotation: %u\n", val);
++                      return -EINVAL;
++              }
++
++              props->rotation = val;
++              dev_dbg(dev, "device rotation: %u\n", val);
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(v4l2_fwnode_device_parse);
++
+ static int
+ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
+                                         struct v4l2_async_notifier *notifier,
+--- a/include/media/v4l2-fwnode.h
++++ b/include/media/v4l2-fwnode.h
+@@ -110,6 +110,36 @@ struct v4l2_fwnode_endpoint {
+ };
+ /**
++ * V4L2_FWNODE_PROPERTY_UNSET - identify a non initialized property
++ *
++ * All properties in &struct v4l2_fwnode_device_properties are initialized
++ * to this value.
++ */
++#define V4L2_FWNODE_PROPERTY_UNSET   (-1U)
++
++/**
++ * enum v4l2_fwnode_orientation - possible device orientation
++ * @V4L2_FWNODE_ORIENTATION_FRONT: device installed on the front side
++ * @V4L2_FWNODE_ORIENTATION_BACK: device installed on the back side
++ * @V4L2_FWNODE_ORIENTATION_EXTERNAL: device externally located
++ */
++enum v4l2_fwnode_orientation {
++      V4L2_FWNODE_ORIENTATION_FRONT,
++      V4L2_FWNODE_ORIENTATION_BACK,
++      V4L2_FWNODE_ORIENTATION_EXTERNAL
++};
++
++/**
++ * struct v4l2_fwnode_device_properties - fwnode device properties
++ * @orientation: device orientation. See &enum v4l2_fwnode_orientation
++ * @rotation: device rotation
++ */
++struct v4l2_fwnode_device_properties {
++      enum v4l2_fwnode_orientation orientation;
++      unsigned int rotation;
++};
++
++/**
+  * struct v4l2_fwnode_link - a link between two endpoints
+  * @local_node: pointer to device_node of this endpoint
+  * @local_port: identifier of the port this endpoint belongs to
+@@ -234,6 +264,23 @@ int v4l2_fwnode_parse_link(struct fwnode
+ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link);
+ /**
++ * v4l2_fwnode_device_parse() - parse fwnode device properties
++ * @dev: pointer to &struct device
++ * @props: pointer to &struct v4l2_fwnode_device_properties where to store the
++ *       parsed properties values
++ *
++ * This function parses and validates the V4L2 fwnode device properties from the
++ * firmware interface, and fills the @struct v4l2_fwnode_device_properties
++ * provided by the caller.
++ *
++ * Return:
++ *    % 0 on success
++ *    %-EINVAL if a parsed property value is not valid
++ */
++int v4l2_fwnode_device_parse(struct device *dev,
++                           struct v4l2_fwnode_device_properties *props);
++
++/**
+  * typedef parse_endpoint_func - Driver's callback function to be called on
+  *    each V4L2 fwnode endpoint.
+  *
diff --git a/target/linux/bcm27xx/patches-5.4/950-0908-media-v4l2-ctrls-Add-helper-to-register-properties.patch b/target/linux/bcm27xx/patches-5.4/950-0908-media-v4l2-ctrls-Add-helper-to-register-properties.patch
new file mode 100644 (file)
index 0000000..a76de95
--- /dev/null
@@ -0,0 +1,114 @@
+From 67429ff939ad15a313663a05461d7a07d209449f Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:52 +0200
+Subject: [PATCH] media: v4l2-ctrls: Add helper to register
+ properties
+
+Add an helper function to v4l2-ctrls to register controls associated
+with a device property.
+
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit e0a360630debdf12355d9ec9f1417172c3fa6756 upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/v4l2-core/v4l2-ctrls.c | 40 ++++++++++++++++++++++++++++
+ include/media/v4l2-ctrls.h           | 26 ++++++++++++++++++
+ 2 files changed, 66 insertions(+)
+
+--- a/drivers/media/v4l2-core/v4l2-ctrls.c
++++ b/drivers/media/v4l2-core/v4l2-ctrls.c
+@@ -17,6 +17,7 @@
+ #include <media/v4l2-ctrls.h>
+ #include <media/v4l2-event.h>
+ #include <media/v4l2-dev.h>
++#include <media/v4l2-fwnode.h>
+ #define dprintk(vdev, fmt, arg...) do {                                       \
+       if (!WARN_ON(!(vdev)) && ((vdev)->dev_debug & V4L2_DEV_DEBUG_CTRL)) \
+@@ -4577,3 +4578,42 @@ __poll_t v4l2_ctrl_poll(struct file *fil
+       return 0;
+ }
+ EXPORT_SYMBOL(v4l2_ctrl_poll);
++
++int v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl,
++                                  const struct v4l2_ctrl_ops *ctrl_ops,
++                                  const struct v4l2_fwnode_device_properties *p)
++{
++      if (p->orientation != V4L2_FWNODE_PROPERTY_UNSET) {
++              u32 orientation_ctrl;
++
++              switch (p->orientation) {
++              case V4L2_FWNODE_ORIENTATION_FRONT:
++                      orientation_ctrl = V4L2_CAMERA_ORIENTATION_FRONT;
++                      break;
++              case V4L2_FWNODE_ORIENTATION_BACK:
++                      orientation_ctrl = V4L2_CAMERA_ORIENTATION_BACK;
++                      break;
++              case V4L2_FWNODE_ORIENTATION_EXTERNAL:
++                      orientation_ctrl = V4L2_CAMERA_ORIENTATION_EXTERNAL;
++                      break;
++              default:
++                      return -EINVAL;
++              }
++              if (!v4l2_ctrl_new_std_menu(hdl, ctrl_ops,
++                                          V4L2_CID_CAMERA_ORIENTATION,
++                                          V4L2_CAMERA_ORIENTATION_EXTERNAL, 0,
++                                          orientation_ctrl))
++                      return hdl->error;
++      }
++
++      if (p->rotation != V4L2_FWNODE_PROPERTY_UNSET) {
++              if (!v4l2_ctrl_new_std(hdl, ctrl_ops,
++                                     V4L2_CID_CAMERA_SENSOR_ROTATION,
++                                     p->rotation, p->rotation, 1,
++                                     p->rotation))
++                      return hdl->error;
++      }
++
++      return hdl->error;
++}
++EXPORT_SYMBOL(v4l2_ctrl_new_fwnode_properties);
+--- a/include/media/v4l2-ctrls.h
++++ b/include/media/v4l2-ctrls.h
+@@ -29,6 +29,7 @@ struct v4l2_ctrl_handler;
+ struct v4l2_ctrl_helper;
+ struct v4l2_ctrl;
+ struct video_device;
++struct v4l2_fwnode_device_properties;
+ struct v4l2_subdev;
+ struct v4l2_subscribed_event;
+ struct v4l2_fh;
+@@ -1379,4 +1380,29 @@ int v4l2_ctrl_subdev_subscribe_event(str
+  */
+ int v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd);
++/**
++ * v4l2_ctrl_new_fwnode_properties() - Register controls for the device
++ *                                   properties
++ *
++ * @hdl: pointer to &struct v4l2_ctrl_handler to register controls on
++ * @ctrl_ops: pointer to &struct v4l2_ctrl_ops to register controls with
++ * @p: pointer to &struct v4l2_fwnode_device_properties
++ *
++ * This function registers controls associated to device properties, using the
++ * property values contained in @p parameter, if the property has been set to
++ * a value.
++ *
++ * Currently the following v4l2 controls are parsed and registered:
++ * - V4L2_CID_CAMERA_ORIENTATION
++ * - V4L2_CID_CAMERA_SENSOR_ROTATION;
++ *
++ * Controls already registered by the caller with the @hdl control handler are
++ * not overwritten. Callers should register the controls they want to handle
++ * themselves before calling this function.
++ *
++ * Return: 0 on success, a negative error code on failure.
++ */
++int v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl,
++                                  const struct v4l2_ctrl_ops *ctrl_ops,
++                                  const struct v4l2_fwnode_device_properties *p);
+ #endif
diff --git a/target/linux/bcm27xx/patches-5.4/950-0909-media-i2c-ov5647-Parse-and-register-properties.patch b/target/linux/bcm27xx/patches-5.4/950-0909-media-i2c-ov5647-Parse-and-register-properties.patch
new file mode 100644 (file)
index 0000000..ac7d70c
--- /dev/null
@@ -0,0 +1,49 @@
+From 4b738c3d5c0f2719642b9515cece7fbfce9dc108 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Sat, 4 Jul 2020 01:45:08 +0300
+Subject: [PATCH] media: i2c: ov5647: Parse and register properties
+
+Parse device properties and register controls for them using the V4L2
+fwnode properties helpers.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/i2c/ov5647.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/ov5647.c
++++ b/drivers/media/i2c/ov5647.c
+@@ -1501,6 +1501,7 @@ static int ov5647_probe(struct i2c_clien
+       struct device_node *np = client->dev.of_node;
+       u32 xclk_freq;
+       int hblank, exposure_max, exposure_def;
++      struct v4l2_fwnode_device_properties props;
+       sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
+       if (!sensor)
+@@ -1534,7 +1535,7 @@ static int ov5647_probe(struct i2c_clien
+       mutex_init(&sensor->lock);
+       /* Initialise controls. */
+-      v4l2_ctrl_handler_init(&sensor->ctrls, 7);
++      v4l2_ctrl_handler_init(&sensor->ctrls, 9);
+       v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
+                         V4L2_CID_AUTOGAIN,
+                         0,  /* min */
+@@ -1598,6 +1599,16 @@ static int ov5647_probe(struct i2c_clien
+                       __func__, ret);
+               goto error;
+       }
++
++      ret = v4l2_fwnode_device_parse(&client->dev, &props);
++      if (ret)
++              goto error;
++
++      ret = v4l2_ctrl_new_fwnode_properties(&sensor->ctrls, &ov5647_ctrl_ops,
++                                            &props);
++      if (ret)
++              goto error;
++
+       sensor->sd.ctrl_handler = &sensor->ctrls;
+       /* Write out the register set over I2C on stream-on. */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0910-media-i2c-imx219-Parse-and-register-properties.patch b/target/linux/bcm27xx/patches-5.4/950-0910-media-i2c-imx219-Parse-and-register-properties.patch
new file mode 100644 (file)
index 0000000..dc5584e
--- /dev/null
@@ -0,0 +1,51 @@
+From db0889b08409484160a9082bc0b5f39877fe9591 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Sat, 9 May 2020 11:04:55 +0200
+Subject: [PATCH] media: i2c: imx219: Parse and register properties
+
+Parse device properties and register controls for them using the newly
+introduced helpers.
+
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+Commit ad3a44cbd1b2e1559c6b93e80dc0c9c29632969a upstream
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/i2c/imx219.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -1348,11 +1348,12 @@ static int imx219_init_controls(struct i
+       struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
+       struct v4l2_ctrl_handler *ctrl_hdlr;
+       unsigned int height = imx219->mode->height;
++      struct v4l2_fwnode_device_properties props;
+       int exposure_max, exposure_def, hblank;
+       int i, ret;
+       ctrl_hdlr = &imx219->ctrl_handler;
+-      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9);
++      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 11);
+       if (ret)
+               return ret;
+@@ -1431,6 +1432,15 @@ static int imx219_init_controls(struct i
+               goto error;
+       }
++      ret = v4l2_fwnode_device_parse(&client->dev, &props);
++      if (ret)
++              goto error;
++
++      ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops,
++                                            &props);
++      if (ret)
++              goto error;
++
+       imx219->sd.ctrl_handler = ctrl_hdlr;
+       return 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0911-media-i2c-imx477-Parse-and-register-properties.patch b/target/linux/bcm27xx/patches-5.4/950-0911-media-i2c-imx477-Parse-and-register-properties.patch
new file mode 100644 (file)
index 0000000..fe022c9
--- /dev/null
@@ -0,0 +1,45 @@
+From df12dbc41bbdb2b949eb395088f9d6b197d9db8a Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Sat, 4 Jul 2020 01:45:08 +0300
+Subject: [PATCH] media: i2c: imx477: Parse and register properties
+
+Parse device properties and register controls for them using the V4L2
+fwnode properties helpers.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/i2c/imx477.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/i2c/imx477.c
++++ b/drivers/media/i2c/imx477.c
+@@ -1957,11 +1957,12 @@ static int imx477_init_controls(struct i
+ {
+       struct v4l2_ctrl_handler *ctrl_hdlr;
+       struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
++      struct v4l2_fwnode_device_properties props;
+       unsigned int i;
+       int ret;
+       ctrl_hdlr = &imx477->ctrl_handler;
+-      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 14);
++      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16);
+       if (ret)
+               return ret;
+@@ -2045,6 +2046,15 @@ static int imx477_init_controls(struct i
+               goto error;
+       }
++      ret = v4l2_fwnode_device_parse(&client->dev, &props);
++      if (ret)
++              goto error;
++
++      ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx477_ctrl_ops,
++                                            &props);
++      if (ret)
++              goto error;
++
+       imx477->sd.ctrl_handler = ctrl_hdlr;
+       /* Setup exposure and frame/line length limits. */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0912-dt-dtoverlays-ov5647-Add-parameter-to-set-camera-mod.patch b/target/linux/bcm27xx/patches-5.4/950-0912-dt-dtoverlays-ov5647-Add-parameter-to-set-camera-mod.patch
new file mode 100644 (file)
index 0000000..23a2fb9
--- /dev/null
@@ -0,0 +1,49 @@
+From 7d2efa734da00de05c8a58688da28cf1e380ef3a Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Sat, 4 Jul 2020 03:04:38 +0300
+Subject: [PATCH] dt/dtoverlays: ov5647: Add parameter to set camera
+ module rotation
+
+Add a rotation DT overlay parameter to allow specifying the camera
+module mounting rotation.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ arch/arm/boot/dts/overlays/README             | 5 +++--
+ arch/arm/boot/dts/overlays/ov5647-overlay.dts | 6 ++++++
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1809,8 +1809,9 @@ Name:   ov5647
+ Info:   Omnivision OV5647 camera module.
+         Uses Unicam 1, which is the standard camera connector on most Pi
+         variants.
+-Load:   dtoverlay=ov5647
+-Params: <None>
++Load:   dtoverlay=ov5647,<param>=<val>
++Params: rotation                Mounting rotation of the camera sensor (0 or
++                                180, default 0)
+ Name:   ov7251
+--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts
+@@ -21,6 +21,8 @@
+                               pwdn-gpios = <&gpio 41 1>, <&gpio 32 1>;
+                               clocks = <&ov5647_clk>;
++                              rotation = <0>;
++
+                               port {
+                                       ov5647_0: endpoint {
+                                               remote-endpoint = <&csi1_ep>;
+@@ -83,4 +85,8 @@
+                       };
+               };
+       };
++
++      __overrides__ {
++              rotation = <&ov5647>,"rotation:0";
++      };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0913-dt-dtoverlays-imx219-Add-parameter-to-set-camera-mod.patch b/target/linux/bcm27xx/patches-5.4/950-0913-dt-dtoverlays-imx219-Add-parameter-to-set-camera-mod.patch
new file mode 100644 (file)
index 0000000..be22dd3
--- /dev/null
@@ -0,0 +1,50 @@
+From 30fbdcf8d58658860e43c0396cb50c5d4ade2dc5 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Sat, 4 Jul 2020 03:04:38 +0300
+Subject: [PATCH] dt/dtoverlays: imx219: Add parameter to set camera
+ module rotation
+
+Add a rotation DT overlay parameter to allow specifying the camera
+module mounting rotation. Set the default rotation to 180 as the module
+is typically mounted upside-down.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ arch/arm/boot/dts/overlays/README             | 5 +++--
+ arch/arm/boot/dts/overlays/imx219-overlay.dts | 6 ++++++
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1433,8 +1433,9 @@ Name:   imx219
+ Info:   Sony IMX219 camera module.
+         Uses Unicam 1, which is the standard camera connector on most Pi
+         variants.
+-Load:   dtoverlay=imx219
+-Params: <None>
++Load:   dtoverlay=imx219,<param>=<val>
++Params: rotation                Mounting rotation of the camera sensor (0 or
++                                180, default 180)
+ Name:   imx290
+--- a/arch/arm/boot/dts/overlays/imx219-overlay.dts
++++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts
+@@ -27,6 +27,8 @@
+                               VDIG-supply = <&imx219_vdig>;   /* 1.8v */
+                               VDDL-supply = <&imx219_vddl>;   /* 1.2v */
++                              rotation = <180>;
++
+                               port {
+                                       imx219_0: endpoint {
+                                               remote-endpoint = <&csi1_ep>;
+@@ -110,4 +112,8 @@
+                       cam0-pwdn      = <&imx219_vana>,"gpio:4";
+               };
+       };
++
++      __overrides__ {
++              rotation = <&imx219>,"rotation:0";
++      };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0914-dt-dtoverlays-imx477-Add-parameter-to-set-camera-mod.patch b/target/linux/bcm27xx/patches-5.4/950-0914-dt-dtoverlays-imx477-Add-parameter-to-set-camera-mod.patch
new file mode 100644 (file)
index 0000000..11a5d3d
--- /dev/null
@@ -0,0 +1,50 @@
+From afed51afadb2f5d43e093c969bdf6535b2ea0ad3 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Sat, 4 Jul 2020 03:04:38 +0300
+Subject: [PATCH] dt/dtoverlays: imx477: Add parameter to set camera
+ module rotation
+
+Add a rotation DT overlay parameter to allow specifying the camera
+module mounting rotation. Set the default rotation to 180 as the module
+is typically mounted upside-down.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ arch/arm/boot/dts/overlays/README             | 5 +++--
+ arch/arm/boot/dts/overlays/imx477-overlay.dts | 6 ++++++
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1458,8 +1458,9 @@ Name:   imx477
+ Info:   Sony IMX477 camera module.
+         Uses Unicam 1, which is the standard camera connector on most Pi
+         variants.
+-Load:   dtoverlay=imx477
+-Params: <None>
++Load:   dtoverlay=imx477,<param>=<val>
++Params: rotation                Mounting rotation of the camera sensor (0 or
++                                180, default 180)
+ Name:   iqaudio-codec
+--- a/arch/arm/boot/dts/overlays/imx477-overlay.dts
++++ b/arch/arm/boot/dts/overlays/imx477-overlay.dts
+@@ -27,6 +27,8 @@
+                               VDIG-supply = <&imx477_vdig>;   /* 1.05v */
+                               VDDL-supply = <&imx477_vddl>;   /* 1.8v */
++                              rotation = <180>;
++
+                               port {
+                                       imx477_0: endpoint {
+                                               remote-endpoint = <&csi1_ep>;
+@@ -110,4 +112,8 @@
+                       cam0-pwdn      = <&imx477_vana>,"gpio:4";
+               };
+       };
++
++      __overrides__ {
++              rotation = <&imx477>,"rotation:0";
++      };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0915-drm-vc4-Add-DRM_MODE_FLAG_DBLCLK-support-to-vc4-fkms.patch b/target/linux/bcm27xx/patches-5.4/950-0915-drm-vc4-Add-DRM_MODE_FLAG_DBLCLK-support-to-vc4-fkms.patch
new file mode 100644 (file)
index 0000000..a7a1d91
--- /dev/null
@@ -0,0 +1,54 @@
+From 16349a9b271d331a496a482f46f41a3e1db56891 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 16 Jul 2020 12:02:47 +0100
+Subject: [PATCH] drm/vc4: Add DRM_MODE_FLAG_DBLCLK support to
+ vc4-fkms
+
+480i and several other modes use DRM_MODE_FLAG_DBLCLK and pixel
+replication.
+
+Add in flags for that so that FKMS can select CEA modes 6 & 7.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -158,6 +158,8 @@ struct set_timings {
+ #define TIMINGS_FLAGS_RGB_LIMITED     BIT(8)
+ /* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
+ #define TIMINGS_FLAGS_DVI             BIT(9)
++/* Double clock */
++#define TIMINGS_FLAGS_DBL_CLK         BIT(10)
+ };
+ struct mailbox_set_mode {
+@@ -946,6 +948,8 @@ static void vc4_crtc_mode_set_nofb(struc
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               mb.timings.flags |= TIMINGS_FLAGS_INTERLACE;
++      if (mode->flags & DRM_MODE_FLAG_DBLCLK)
++              mb.timings.flags |= TIMINGS_FLAGS_DBL_CLK;
+       mb.timings.video_id_code = frame.avi.video_code;
+@@ -1104,11 +1108,16 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+        */
+       if (fkms->bcm2711 &&
+           (vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) &&
++          !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
+           ((mode->hdisplay |                          /* active */
+             (mode->hsync_start - mode->hdisplay) |    /* front porch */
+             (mode->hsync_end - mode->hsync_start) |   /* sync pulse */
+-            (mode->htotal - mode->hsync_end)) & 1))   /* back porch */
++            (mode->htotal - mode->hsync_end)) & 1))   /* back porch */ {
++              DRM_DEBUG_KMS("[CRTC:%d] Odd timing rejected %u %u %u %u.\n",
++                            crtc->base.id, mode->hdisplay, mode->hsync_start,
++                            mode->hsync_end, mode->htotal);
+               return MODE_H_ILLEGAL;
++      }
+       return MODE_OK;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0916-leds-Add-the-actpwr-trigger.patch b/target/linux/bcm27xx/patches-5.4/950-0916-leds-Add-the-actpwr-trigger.patch
new file mode 100644 (file)
index 0000000..2f0aaa0
--- /dev/null
@@ -0,0 +1,236 @@
+From 6586d75915287dd336b71e17826f037be7926ebe Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 13 Jul 2020 10:33:19 +0100
+Subject: [PATCH] leds: Add the actpwr trigger
+
+The actpwr trigger is a meta trigger that cycles between an inverted
+mmc0 and default-on. It is written in a way that could fairly easily
+be generalised to support alternative sets of source triggers.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/leds/trigger/Kconfig          |  11 ++
+ drivers/leds/trigger/Makefile         |   1 +
+ drivers/leds/trigger/ledtrig-actpwr.c | 191 ++++++++++++++++++++++++++
+ 3 files changed, 203 insertions(+)
+ create mode 100644 drivers/leds/trigger/ledtrig-actpwr.c
+
+--- a/drivers/leds/trigger/Kconfig
++++ b/drivers/leds/trigger/Kconfig
+@@ -151,4 +151,15 @@ config LEDS_TRIGGER_AUDIO
+         the audio mute and mic-mute changes.
+         If unsure, say N
++config LEDS_TRIGGER_ACTPWR
++      tristate "ACT/PWR Input Trigger"
++      depends on LEDS_TRIGGERS
++      help
++        This trigger is intended for platforms that have one software-
++        controllable LED and no dedicated activity or power LEDs, hence the
++        need to make the one LED perform both functions. It cycles between
++        default-on and an inverted mmc0 every 500ms, guaranteeing that it is
++        on for at least half of the time.
++        If unsure, say N.
++
+ endif # LEDS_TRIGGERS
+--- a/drivers/leds/trigger/Makefile
++++ b/drivers/leds/trigger/Makefile
+@@ -16,3 +16,4 @@ obj-$(CONFIG_LEDS_TRIGGER_PANIC)     += ledt
+ obj-$(CONFIG_LEDS_TRIGGER_NETDEV)     += ledtrig-netdev.o
+ obj-$(CONFIG_LEDS_TRIGGER_PATTERN)    += ledtrig-pattern.o
+ obj-$(CONFIG_LEDS_TRIGGER_AUDIO)      += ledtrig-audio.o
++obj-$(CONFIG_LEDS_TRIGGER_ACTPWR)     += ledtrig-actpwr.o
+--- /dev/null
++++ b/drivers/leds/trigger/ledtrig-actpwr.c
+@@ -0,0 +1,191 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Activity/power trigger
++ *
++ * Copyright (C) 2020 Raspberry Pi (Trading) Ltd.
++ *
++ * Based on Atsushi Nemoto's ledtrig-heartbeat.c, although there may be
++ * nothing left of the original now.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/leds.h>
++#include "../leds.h"
++
++enum {
++      TRIG_ACT,
++      TRIG_PWR,
++
++      TRIG_COUNT
++};
++
++struct actpwr_trig_src {
++      const char *name;
++      int interval;
++      bool invert;
++};
++
++struct actpwr_vled {
++      struct led_classdev cdev;
++      struct actpwr_trig_data *parent;
++      enum led_brightness value;
++      unsigned int interval;
++      bool invert;
++};
++
++struct actpwr_trig_data {
++      struct led_trigger trig;
++      struct actpwr_vled virt_leds[TRIG_COUNT];
++      struct actpwr_vled *active;
++      struct timer_list timer;
++      int next_active;
++};
++
++static int actpwr_trig_activate(struct led_classdev *led_cdev);
++static void actpwr_trig_deactivate(struct led_classdev *led_cdev);
++
++static const struct actpwr_trig_src actpwr_trig_sources[TRIG_COUNT] = {
++      [TRIG_ACT] = { "mmc0", 500, true },
++      [TRIG_PWR] = { "default-on", 500, false },
++};
++
++static struct actpwr_trig_data actpwr_data = {
++      {
++              .name     = "actpwr",
++              .activate = actpwr_trig_activate,
++              .deactivate = actpwr_trig_deactivate,
++      }
++};
++
++static void actpwr_brightness_set(struct led_classdev *led_cdev,
++                                enum led_brightness value)
++{
++      struct actpwr_vled *vled = container_of(led_cdev, struct actpwr_vled,
++                                             cdev);
++      struct actpwr_trig_data *trig = vled->parent;
++
++      if (vled->invert)
++              value = !value;
++      vled->value = value;
++
++      if (vled == trig->active)
++              led_trigger_event(&trig->trig, value);
++}
++
++static int actpwr_brightness_set_blocking(struct led_classdev *led_cdev,
++                                        enum led_brightness value)
++{
++      actpwr_brightness_set(led_cdev, value);
++      return 0;
++}
++
++static enum led_brightness actpwr_brightness_get(struct led_classdev *led_cdev)
++{
++      struct actpwr_vled *vled = container_of(led_cdev, struct actpwr_vled,
++                                            cdev);
++
++      return vled->value;
++}
++
++static void actpwr_trig_cycle(struct timer_list *t)
++{
++      struct actpwr_trig_data *trig  = &actpwr_data;
++      struct actpwr_vled *active;
++      enum led_brightness value;
++
++      active = &trig->virt_leds[trig->next_active];
++      trig->active = active;
++      trig->next_active = (trig->next_active + 1) % TRIG_COUNT;
++
++      led_trigger_event(&trig->trig, active->value);
++
++      mod_timer(&trig->timer, jiffies + msecs_to_jiffies(active->interval));
++}
++
++static int actpwr_trig_activate(struct led_classdev *led_cdev)
++{
++      struct actpwr_trig_data *trig  = &actpwr_data;
++
++      /* Start the timer if this is the first LED */
++      if (!trig->active)
++              actpwr_trig_cycle(&trig->timer);
++      else
++              led_set_brightness_nosleep(led_cdev, trig->active->value);
++
++      return 0;
++}
++
++static void actpwr_trig_deactivate(struct led_classdev *led_cdev)
++{
++      struct actpwr_trig_data *trig  = &actpwr_data;
++
++      if (list_empty(&trig->trig.led_cdevs)) {
++              del_timer_sync(&trig->timer);
++              trig->active = NULL;
++      }
++}
++
++static int __init actpwr_trig_init(void)
++{
++      struct actpwr_trig_data *trig  = &actpwr_data;
++      int ret = 0;
++      int i;
++
++      timer_setup(&trig->timer, actpwr_trig_cycle, 0);
++
++      /* Register one "LED" for each source trigger */
++      for (i = 0; i < TRIG_COUNT; i++)
++      {
++              struct actpwr_vled *vled = &trig->virt_leds[i];
++              struct led_classdev *cdev = &vled->cdev;
++              const struct actpwr_trig_src *src = &actpwr_trig_sources[i];
++
++              vled->parent = trig;
++              vled->interval = src->interval;
++              vled->invert = src->invert;
++              cdev->name = src->name;
++              cdev->brightness_set = actpwr_brightness_set;
++              cdev->brightness_set_blocking = actpwr_brightness_set_blocking;
++              cdev->brightness_get = actpwr_brightness_get;
++              cdev->default_trigger = src->name;
++              ret = led_classdev_register(NULL, cdev);
++              if (ret)
++                      goto error_classdev;
++      }
++
++      ret = led_trigger_register(&trig->trig);
++      if (ret)
++              goto error_classdev;
++
++      return 0;
++
++error_classdev:
++      while (i > 0)
++      {
++              i--;
++              led_classdev_unregister(&trig->virt_leds[i].cdev);
++      }
++
++      return ret;
++}
++
++static void __exit actpwr_trig_exit(void)
++{
++      int i;
++
++      led_trigger_unregister(&actpwr_data.trig);
++      for (i = 0; i < TRIG_COUNT; i++)
++      {
++              led_classdev_unregister(&actpwr_data.virt_leds[i].cdev);
++      }
++}
++
++module_init(actpwr_trig_init);
++module_exit(actpwr_trig_exit);
++
++MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
++MODULE_DESCRIPTION("ACT/PWR LED trigger");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0917-ARM-dts-Select-the-actpwr-LED-trigger-on-Zeroes.patch b/target/linux/bcm27xx/patches-5.4/950-0917-ARM-dts-Select-the-actpwr-LED-trigger-on-Zeroes.patch
new file mode 100644 (file)
index 0000000..02f425a
--- /dev/null
@@ -0,0 +1,41 @@
+From 990bc7c8a234a0f446a7d56067b1a9f8348e0f35 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 16 Jul 2020 18:19:58 +0100
+Subject: [PATCH] ARM: dts: Select the actpwr LED trigger on Zeroes
+
+The new "actpwr" LED trigger guarantees that the combined PWR and ACT
+LED is on for at least half of every second. Under heavy SD card
+load it emits a steady 1Hz square wave.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 4 ++--
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts   | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -144,8 +144,8 @@
+ &leds {
+       act_led: act {
+               label = "led0";
+-              linux,default-trigger = "mmc0";
+-              gpios = <&gpio 47 0>;
++              linux,default-trigger = "actpwr";
++              gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
+       };
+ };
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -98,8 +98,8 @@
+ &leds {
+       act_led: act {
+               label = "led0";
+-              linux,default-trigger = "mmc0";
+-              gpios = <&gpio 47 0>;
++              linux,default-trigger = "actpwr";
++              gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0918-staging-vc04_services-isp-Rework-lens-shading-to-tak.patch b/target/linux/bcm27xx/patches-5.4/950-0918-staging-vc04_services-isp-Rework-lens-shading-to-tak.patch
new file mode 100644 (file)
index 0000000..8748214
--- /dev/null
@@ -0,0 +1,87 @@
+From 7504f92483407233d9093e164d8f001db5c374e5 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 8 May 2020 22:05:29 +0100
+Subject: [PATCH] staging: vc04_services: isp: Rework lens shading to
+ take a dmabuf
+
+This removes the need for the client to use vcsm at all.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-isp/bcm2835-v4l2-isp.c            | 36 +++++++++++++++++--
+ include/uapi/linux/bcm2835-isp.h              |  4 +--
+ 2 files changed, 35 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -21,6 +21,8 @@
+ #include "vchiq-mmal/mmal-parameters.h"
+ #include "vchiq-mmal/mmal-vchiq.h"
++#include "vc-sm-cma/vc_sm_knl.h"
++
+ #include "bcm2835_isp_ctrls.h"
+ #include "bcm2835_isp_fmts.h"
+@@ -722,10 +724,38 @@ static int bcm2835_isp_s_ctrl(struct v4l
+                                   sizeof(struct bcm2835_isp_custom_ccm));
+               break;
+       case V4L2_CID_USER_BCM2835_ISP_LENS_SHADING:
+-              ret = set_isp_param(node, MMAL_PARAMETER_LENS_SHADING_OVERRIDE,
+-                                  ctrl->p_new.p_u8,
+-                                  sizeof(struct bcm2835_isp_lens_shading));
++      {
++              struct bcm2835_isp_lens_shading ls;
++              struct dma_buf *dmabuf;
++              void *vcsm_handle;
++
++              memcpy(&ls, ctrl->p_new.p_u8,
++                     sizeof(struct bcm2835_isp_lens_shading));
++
++              dmabuf = dma_buf_get(ls.dmabuf);
++              if (!dmabuf)
++                      return -EINVAL;
++
++              ret = vc_sm_cma_import_dmabuf(dmabuf,
++                                            &vcsm_handle);
++              if (ret) {
++                      dma_buf_put(dmabuf);
++                      return -EINVAL;
++              }
++
++              ls.dmabuf = vc_sm_cma_int_handle(vcsm_handle);
++              if (ls.dmabuf)
++                      ret = set_isp_param(node,
++                                          MMAL_PARAMETER_LENS_SHADING_OVERRIDE,
++                                          &ls,
++                                          sizeof(struct bcm2835_isp_lens_shading));
++              else
++                      ret = -EINVAL;
++
++              vc_sm_cma_free(vcsm_handle);
++              dma_buf_put(dmabuf);
+               break;
++      }
+       case V4L2_CID_USER_BCM2835_ISP_BLACK_LEVEL:
+               ret = set_isp_param(node, MMAL_PARAMETER_BLACK_LEVEL,
+                                   ctrl->p_new.p_u8,
+--- a/include/uapi/linux/bcm2835-isp.h
++++ b/include/uapi/linux/bcm2835-isp.h
+@@ -108,7 +108,7 @@ enum bcm2835_isp_gain_format {
+  * @grid_stride:      Row to row distance (in grid cells) between grid cells
+  *                    in the same horizontal location.
+  * @grid_height:      Height of lens shading tables in grid cells.
+- * @mem_handle_table: Memory handle to the tables.
++ * @dmabuf:           dmabuf file handle containing the table.
+  * @ref_transform:    Reference transform - unsupported, please pass zero.
+  * @corner_sampled:   Whether the gains are sampled at the corner points
+  *                    of the grid cells or in the cell centres.
+@@ -120,7 +120,7 @@ struct bcm2835_isp_lens_shading {
+       __u32 grid_width;
+       __u32 grid_stride;
+       __u32 grid_height;
+-      __u32 mem_handle_table;
++      __s32 dmabuf;
+       __u32 ref_transform;
+       __u32 corner_sampled;
+       __u32 gain_format;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0919-Mute-bug-fix-for-the-Audioinjector.net-isolated-soun.patch b/target/linux/bcm27xx/patches-5.4/950-0919-Mute-bug-fix-for-the-Audioinjector.net-isolated-soun.patch
new file mode 100644 (file)
index 0000000..10fe757
--- /dev/null
@@ -0,0 +1,64 @@
+From 11a2b192e0a8b7514895f9f6b7451f4c6ddd0a22 Mon Sep 17 00:00:00 2001
+From: Matt Flax <flatmax@flatmax.org>
+Date: Fri, 17 Jul 2020 09:17:36 +1000
+Subject: [PATCH] Mute bug fix for the Audioinjector.net isolated
+ soundcard.
+
+---
+ .../bcm/audioinjector-isolated-soundcard.c    | 26 +++----------------
+ 1 file changed, 3 insertions(+), 23 deletions(-)
+
+--- a/sound/soc/bcm/audioinjector-isolated-soundcard.c
++++ b/sound/soc/bcm/audioinjector-isolated-soundcard.c
+@@ -42,41 +42,20 @@ static int audioinjector_isolated_dai_in
+       int ret=snd_soc_dai_set_sysclk(rtd->codec_dai, 0, 24576000, 0);
+       if (ret)
+               return ret;
+-
+       return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, 64);
+ }
+ static int audioinjector_isolated_startup(struct snd_pcm_substream *substream)
+ {
+       snd_pcm_hw_constraint_list(substream->runtime, 0,
+-                              SNDRV_PCM_HW_PARAM_RATE, &audioinjector_isolated_constraints);
+-
+-      return 0;
+-}
++                      SNDRV_PCM_HW_PARAM_RATE, &audioinjector_isolated_constraints);
+-static int audioinjector_isolated_trigger(struct snd_pcm_substream *substream,
+-                                                              int cmd){
+-
+-      switch (cmd) {
+-      case SNDRV_PCM_TRIGGER_STOP:
+-      case SNDRV_PCM_TRIGGER_SUSPEND:
+-      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+-              gpiod_set_value(mute_gpio, 0);
+-              break;
+-      case SNDRV_PCM_TRIGGER_START:
+-      case SNDRV_PCM_TRIGGER_RESUME:
+-      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+-              gpiod_set_value(mute_gpio, 1);
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
++      gpiod_set_value(mute_gpio, 1);
+       return 0;
+ }
+ static struct snd_soc_ops audioinjector_isolated_ops = {
+       .startup        = audioinjector_isolated_startup,
+-      .trigger = audioinjector_isolated_trigger,
+ };
+ SND_SOC_DAILINK_DEFS(audioinjector_isolated,
+@@ -153,6 +132,7 @@ static int audioinjector_isolated_probe(
+                       dev_err(&pdev->dev, "mute gpio not found in dt overlay\n");
+                       return PTR_ERR(mute_gpio);
+               }
++              gpiod_set_value(mute_gpio, 0);
+       }
+       ret = devm_snd_soc_register_card(&pdev->dev, card);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0920-vc4-Report-channel-mapping-back-to-userspace.patch b/target/linux/bcm27xx/patches-5.4/950-0920-vc4-Report-channel-mapping-back-to-userspace.patch
new file mode 100644 (file)
index 0000000..8c4e101
--- /dev/null
@@ -0,0 +1,504 @@
+From 058328afcdd3d5c9531cfac8b980d0c0db75856f Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 20 Apr 2020 18:00:38 +0100
+Subject: [PATCH] vc4: Report channel mapping back to userspace
+
+This follows logic in hdmi-codec.c to use speaker layout
+from ELD to choose a suitable speaker mapping based on
+number of channels requested and signal that in audio
+infoframe  and report this back to userspace.
+
+This allows apps like speaker-test and kodi to get the
+output to the right speakers.
+
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 415 +++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_hdmi.h |   3 +
+ 2 files changed, 418 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -48,6 +48,7 @@
+ #include <sound/pcm_drm_eld.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc.h>
++#include <sound/tlv.h>
+ #include "media/cec.h"
+ #include "vc4_drv.h"
+ #include "vc4_hdmi.h"
+@@ -82,6 +83,311 @@
+ #define CEC_CLOCK_FREQ 40000
+ #define VC4_HSM_CLOCK 163682864
++#define HDMI_CODEC_CHMAP_IDX_UNKNOWN  -1
++
++/*
++ * CEA speaker placement for HDMI 1.4:
++ *
++ *  FL  FLC   FC   FRC   FR   FRW
++ *
++ *                                  LFE
++ *
++ *  RL  RLC   RC   RRC   RR
++ *
++ *  Speaker placement has to be extended to support HDMI 2.0
++ */
++enum hdmi_codec_cea_spk_placement {
++      FL  = BIT(0),   /* Front Left           */
++      FC  = BIT(1),   /* Front Center         */
++      FR  = BIT(2),   /* Front Right          */
++      FLC = BIT(3),   /* Front Left Center    */
++      FRC = BIT(4),   /* Front Right Center   */
++      RL  = BIT(5),   /* Rear Left            */
++      RC  = BIT(6),   /* Rear Center          */
++      RR  = BIT(7),   /* Rear Right           */
++      RLC = BIT(8),   /* Rear Left Center     */
++      RRC = BIT(9),   /* Rear Right Center    */
++      LFE = BIT(10),  /* Low Frequency Effect */
++};
++
++/*
++ * cea Speaker allocation structure
++ */
++struct hdmi_codec_cea_spk_alloc {
++      const int ca_id;
++      unsigned int n_ch;
++      unsigned long mask;
++};
++
++/* Channel maps  stereo HDMI */
++static const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = {
++      { .channels = 2,
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
++      { }
++};
++
++/* Channel maps for multi-channel playbacks, up to 8 n_ch */
++static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
++      { .channels = 2, /* CA_ID 0x00 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
++      { .channels = 4, /* CA_ID 0x01 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA } },
++      { .channels = 4, /* CA_ID 0x02 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC } },
++      { .channels = 4, /* CA_ID 0x03 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC } },
++      { .channels = 6, /* CA_ID 0x04 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 6, /* CA_ID 0x05 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 6, /* CA_ID 0x06 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 6, /* CA_ID 0x07 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 6, /* CA_ID 0x08 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
++      { .channels = 6, /* CA_ID 0x09 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
++      { .channels = 6, /* CA_ID 0x0A */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
++      { .channels = 6, /* CA_ID 0x0B */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
++      { .channels = 8, /* CA_ID 0x0C */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 8, /* CA_ID 0x0D */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 8, /* CA_ID 0x0E */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 8, /* CA_ID 0x0F */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },
++      { .channels = 8, /* CA_ID 0x10 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
++      { .channels = 8, /* CA_ID 0x11 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
++      { .channels = 8, /* CA_ID 0x12 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
++      { .channels = 8, /* CA_ID 0x13 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,
++                 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },
++      { .channels = 8, /* CA_ID 0x14 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x15 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x16 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x17 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x18 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x19 */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x1A */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x1B */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x1C */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x1D */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x1E */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { .channels = 8, /* CA_ID 0x1F */
++        .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,
++                 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,
++                 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },
++      { }
++};
++
++/*
++ * hdmi_codec_channel_alloc: speaker configuration available for CEA
++ *
++ * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct
++ * The preceding ones have better chances to be selected by
++ * hdmi_codec_get_ch_alloc_table_idx().
++ */
++static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
++      { .ca_id = 0x00, .n_ch = 2,
++        .mask = FL | FR},
++      /* 2.1 */
++      { .ca_id = 0x01, .n_ch = 4,
++        .mask = FL | FR | LFE},
++      /* Dolby Surround */
++      { .ca_id = 0x02, .n_ch = 4,
++        .mask = FL | FR | FC },
++      /* surround51 */
++      { .ca_id = 0x0b, .n_ch = 6,
++        .mask = FL | FR | LFE | FC | RL | RR},
++      /* surround40 */
++      { .ca_id = 0x08, .n_ch = 6,
++        .mask = FL | FR | RL | RR },
++      /* surround41 */
++      { .ca_id = 0x09, .n_ch = 6,
++        .mask = FL | FR | LFE | RL | RR },
++      /* surround50 */
++      { .ca_id = 0x0a, .n_ch = 6,
++        .mask = FL | FR | FC | RL | RR },
++      /* 6.1 */
++      { .ca_id = 0x0f, .n_ch = 8,
++        .mask = FL | FR | LFE | FC | RL | RR | RC },
++      /* surround71 */
++      { .ca_id = 0x13, .n_ch = 8,
++        .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },
++      /* others */
++      { .ca_id = 0x03, .n_ch = 8,
++        .mask = FL | FR | LFE | FC },
++      { .ca_id = 0x04, .n_ch = 8,
++        .mask = FL | FR | RC},
++      { .ca_id = 0x05, .n_ch = 8,
++        .mask = FL | FR | LFE | RC },
++      { .ca_id = 0x06, .n_ch = 8,
++        .mask = FL | FR | FC | RC },
++      { .ca_id = 0x07, .n_ch = 8,
++        .mask = FL | FR | LFE | FC | RC },
++      { .ca_id = 0x0c, .n_ch = 8,
++        .mask = FL | FR | RC | RL | RR },
++      { .ca_id = 0x0d, .n_ch = 8,
++        .mask = FL | FR | LFE | RL | RR | RC },
++      { .ca_id = 0x0e, .n_ch = 8,
++        .mask = FL | FR | FC | RL | RR | RC },
++      { .ca_id = 0x10, .n_ch = 8,
++        .mask = FL | FR | RL | RR | RLC | RRC },
++      { .ca_id = 0x11, .n_ch = 8,
++        .mask = FL | FR | LFE | RL | RR | RLC | RRC },
++      { .ca_id = 0x12, .n_ch = 8,
++        .mask = FL | FR | FC | RL | RR | RLC | RRC },
++      { .ca_id = 0x14, .n_ch = 8,
++        .mask = FL | FR | FLC | FRC },
++      { .ca_id = 0x15, .n_ch = 8,
++        .mask = FL | FR | LFE | FLC | FRC },
++      { .ca_id = 0x16, .n_ch = 8,
++        .mask = FL | FR | FC | FLC | FRC },
++      { .ca_id = 0x17, .n_ch = 8,
++        .mask = FL | FR | LFE | FC | FLC | FRC },
++      { .ca_id = 0x18, .n_ch = 8,
++        .mask = FL | FR | RC | FLC | FRC },
++      { .ca_id = 0x19, .n_ch = 8,
++        .mask = FL | FR | LFE | RC | FLC | FRC },
++      { .ca_id = 0x1a, .n_ch = 8,
++        .mask = FL | FR | RC | FC | FLC | FRC },
++      { .ca_id = 0x1b, .n_ch = 8,
++        .mask = FL | FR | LFE | RC | FC | FLC | FRC },
++      { .ca_id = 0x1c, .n_ch = 8,
++        .mask = FL | FR | RL | RR | FLC | FRC },
++      { .ca_id = 0x1d, .n_ch = 8,
++        .mask = FL | FR | LFE | RL | RR | FLC | FRC },
++      { .ca_id = 0x1e, .n_ch = 8,
++        .mask = FL | FR | FC | RL | RR | FLC | FRC },
++      { .ca_id = 0x1f, .n_ch = 8,
++        .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
++};
++
++static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)
++{
++      int i;
++      static const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {
++              [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,
++              [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,
++      };
++      unsigned long spk_mask = 0;
++
++      for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) {
++              if (spk_alloc & (1 << i))
++                      spk_mask |= hdmi_codec_eld_spk_alloc_bits[i];
++      }
++
++      return spk_mask;
++}
++
++static int hdmi_codec_get_ch_alloc_table_idx(struct vc4_hdmi *vc4_hdmi,
++                                           unsigned char channels)
++{
++      struct drm_connector *connector = &vc4_hdmi->connector;
++      int i;
++      u8 spk_alloc;
++      unsigned long spk_mask;
++      const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc;
++
++      spk_alloc = drm_eld_get_spk_alloc(connector->eld);
++      spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
++
++      for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) {
++              /* If spk_alloc == 0, HDMI is unplugged return stereo config*/
++              if (!spk_alloc && cap->ca_id == 0)
++                      return i;
++              if (cap->n_ch != channels)
++                      continue;
++              if (!(cap->mask == (spk_mask & cap->mask)))
++                      continue;
++              return i;
++      }
++
++      return -EINVAL;
++}
++
++static void hdmi_codec_eld_chmap(struct vc4_hdmi *vc4_hdmi)
++{
++      struct drm_connector *connector = &vc4_hdmi->connector;
++      u8 spk_alloc;
++      unsigned long spk_mask;
++
++      spk_alloc = drm_eld_get_spk_alloc(connector->eld);
++      spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);
++
++      /* Detect if only stereo supported, else return 8 channels mappings */
++      if ((spk_mask & ~(FL | FR)))
++              vc4_hdmi->audio.chmap = hdmi_codec_8ch_chmaps;
++      else
++              vc4_hdmi->audio.chmap = hdmi_codec_stereo_chmaps;
++}
++
+ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
+ {
+       struct drm_info_node *node = (struct drm_info_node *)m->private;
+@@ -350,6 +656,9 @@ static void vc4_hdmi_set_audio_infoframe
+       frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
+       frame.audio.channels = vc4_hdmi->audio.channels;
++      /* Select a channel allocation that matches with ELD and pcm channels */
++      frame.audio.channel_allocation = vc4_hdmi->audio.chmap_idx;
++
+       vc4_hdmi_write_infoframe(encoder, &frame);
+ }
+@@ -881,6 +1190,10 @@ static int vc4_hdmi_audio_startup(struct
+       if (ret)
+               return ret;
++      /* Select chmap supported */
++      vc4_hdmi->audio.max_channels = 8;
++      hdmi_codec_eld_chmap(vc4_hdmi);
++
+       return 0;
+ }
+@@ -967,6 +1280,7 @@ static int vc4_hdmi_audio_prepare(struct
+       u32 channel_map;
+       u32 mai_audio_format;
+       u32 mai_sample_rate;
++      int idx;
+       if (substream != vc4_hdmi->audio.substream)
+               return -EINVAL;
+@@ -1027,6 +1341,14 @@ static int vc4_hdmi_audio_prepare(struct
+       HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
+       vc4_hdmi_set_n_cts(vc4_hdmi);
++      idx = hdmi_codec_get_ch_alloc_table_idx(vc4_hdmi, vc4_hdmi->audio.channels);
++      if (idx < 0) {
++              DRM_ERROR("Not able to map channels to speakers (%d)\n", idx);
++              vc4_hdmi->audio.chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
++      } else {
++              vc4_hdmi->audio.chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
++      }
++
+       return 0;
+ }
+@@ -1145,6 +1467,89 @@ static int vc4_spdif_mask_get(struct snd
+       return 0;
+ }
++/*
++ * ALSA API channel-map control callbacks
++ */
++static int vc4_chmap_ctl_info(struct snd_kcontrol *kcontrol,
++                              struct snd_ctl_elem_info *uinfo)
++{
++      struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
++      struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
++
++      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++      uinfo->count = vc4_hdmi->audio.max_channels;
++      uinfo->value.integer.min = 0;
++      uinfo->value.integer.max = SNDRV_CHMAP_LAST;
++
++      return 0;
++}
++
++static int vc4_chmap_ctl_get(struct snd_kcontrol *kcontrol,
++                           struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
++      struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
++      unsigned const char *map;
++      unsigned int i;
++
++      if (!vc4_hdmi->audio.chmap)
++              return -EINVAL;
++
++      map = vc4_hdmi->audio.chmap[vc4_hdmi->audio.chmap_idx].map;
++
++      for (i = 0; i < vc4_hdmi->audio.max_channels; i++) {
++              if (vc4_hdmi->audio.chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN)
++                      ucontrol->value.integer.value[i] = 0;
++              else
++                      ucontrol->value.integer.value[i] = map[i];
++      }
++      return 0;
++}
++
++static int vc4_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
++                           unsigned int size, unsigned int __user *tlv)
++{
++      struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
++      struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
++      const struct snd_pcm_chmap_elem *map;
++      unsigned int __user *dst;
++      int c, count = 0;
++
++      if (!vc4_hdmi->audio.chmap)
++              return -EINVAL;
++      if (size < 8)
++              return -ENOMEM;
++      if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
++              return -EFAULT;
++      size -= 8;
++      dst = tlv + 2;
++      for (map = vc4_hdmi->audio.chmap; map->channels; map++) {
++              int chs_bytes = map->channels * 4;
++              //if (!valid_chmap_channels(info, map->channels))
++              //      continue;
++              if (size < 8)
++                      return -ENOMEM;
++              if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
++                  put_user(chs_bytes, dst + 1))
++                      return -EFAULT;
++              dst += 2;
++              size -= 8;
++              count += 8;
++              if (size < chs_bytes)
++                      return -ENOMEM;
++              size -= chs_bytes;
++              count += chs_bytes;
++              for (c = 0; c < map->channels; c++) {
++                      if (put_user(map->map[c], dst))
++                              return -EFAULT;
++                      dst++;
++              }
++      }
++      if (put_user(count, tlv + 1))
++              return -EFAULT;
++      return 0;
++}
++
+ static const struct snd_kcontrol_new vc4_hdmi_audio_controls[] = {
+       {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ |
+@@ -1167,6 +1572,16 @@ static const struct snd_kcontrol_new vc4
+               .info =    vc4_spdif_info,
+               .get =     vc4_spdif_mask_get,
+       },
++      {
++              .access = SNDRV_CTL_ELEM_ACCESS_READ |
++                      SNDRV_CTL_ELEM_ACCESS_TLV_READ |
++                      SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
++              .iface = SNDRV_CTL_ELEM_IFACE_PCM,
++              .name = "Playback Channel Map",
++              .info = vc4_chmap_ctl_info,
++              .get = vc4_chmap_ctl_get,
++              .tlv.c = vc4_chmap_ctl_tlv,
++      },
+ };
+ static const struct snd_soc_dapm_widget vc4_hdmi_audio_widgets[] = {
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
+@@ -117,6 +117,9 @@ struct vc4_hdmi_audio {
+       bool streaming;
+       unsigned char iec_status[4];
++      const struct snd_pcm_chmap_elem *chmap;
++      unsigned int chmap_idx;
++      unsigned int max_channels;
+ };
+ /* General HDMI hardware state. */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0921-SQUASH-leds-actpwr-delete-unused-variable.patch b/target/linux/bcm27xx/patches-5.4/950-0921-SQUASH-leds-actpwr-delete-unused-variable.patch
new file mode 100644 (file)
index 0000000..1166f6a
--- /dev/null
@@ -0,0 +1,20 @@
+From 867a447dbe461b6cfdfae2fcd71c449dced9cd8a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 20 Jul 2020 09:35:46 +0100
+Subject: [PATCH] SQUASH: leds: actpwr - delete unused variable
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/leds/trigger/ledtrig-actpwr.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/leds/trigger/ledtrig-actpwr.c
++++ b/drivers/leds/trigger/ledtrig-actpwr.c
+@@ -94,7 +94,6 @@ static void actpwr_trig_cycle(struct tim
+ {
+       struct actpwr_trig_data *trig  = &actpwr_data;
+       struct actpwr_vled *active;
+-      enum led_brightness value;
+       active = &trig->virt_leds[trig->next_active];
+       trig->active = active;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0922-staging-vchiq_arm-children-inherit-DMA-config.patch b/target/linux/bcm27xx/patches-5.4/950-0922-staging-vchiq_arm-children-inherit-DMA-config.patch
new file mode 100644 (file)
index 0000000..9dbc80c
--- /dev/null
@@ -0,0 +1,36 @@
+From 9f0d49445428265cd6cf0862d94bc7f3dd1304d0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 21 Jul 2020 17:34:09 +0100
+Subject: [PATCH] staging: vchiq_arm: children inherit DMA config
+
+Although it is no longer necessary for vchiq's children to have a
+different DMA configuration to the parent, they do still need to
+explicitly to have their DMA configuration set - to be that of the
+parent.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ .../vc04_services/interface/vchiq_arm/vchiq_arm.c      | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -3205,8 +3205,18 @@ vchiq_register_child(struct platform_dev
+       child->dev.of_node = np;
++      /*
++       * We want the dma-ranges etc to be copied from the parent VCHIQ device
++       * to be passed on to the children without a node of their own.
++       */
++      if (!np)
++              np = pdev->dev.of_node;
++
+       of_dma_configure(&child->dev, np, true);
++      if (np != pdev->dev.of_node)
++              of_node_put(np);
++
+       return child;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0923-ARM-dts-2711-DMA-can-address-36-bits.patch b/target/linux/bcm27xx/patches-5.4/950-0923-ARM-dts-2711-DMA-can-address-36-bits.patch
new file mode 100644 (file)
index 0000000..a777379
--- /dev/null
@@ -0,0 +1,25 @@
+From df3f3eba7e6f19694369ea52360c0d5d18d310c3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 22 Jul 2020 17:45:24 +0100
+Subject: [PATCH] ARM: dts: 2711 DMA can address 36 bits
+
+Kernels prior to 5.7 only see the first entry in dma-ranges, so make
+it cover the full addressable range.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -193,8 +193,7 @@
+                <0x0 0x40000000  0x0 0xff800000  0x0 0x00800000>,
+                <0x6 0x00000000  0x6 0x00000000  0x0 0x40000000>,
+                <0x0 0x00000000  0x0 0x00000000  0x0 0xfc000000>;
+-      dma-ranges = <0x0 0x00000000  0x0 0x00000000  0x0 0xfc000000>,
+-                   <0x1 0x00000000  0x1 0x00000000  0x1 0x00000000>;
++      dma-ranges = <0x0 0x00000000  0x0 0x00000000  0x4 0x00000000>;
+       dma40: dma@7e007b00 {
+               compatible = "brcm,bcm2711-dma";
diff --git a/target/linux/bcm27xx/patches-5.4/950-0924-bcm2835-dma-Advertise-the-full-DMA-range.patch b/target/linux/bcm27xx/patches-5.4/950-0924-bcm2835-dma-Advertise-the-full-DMA-range.patch
new file mode 100644 (file)
index 0000000..33c740f
--- /dev/null
@@ -0,0 +1,77 @@
+From bf7baee1935c4d485083c3b3c439631ae4ac3c0f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 22 Jul 2020 17:59:31 +0100
+Subject: [PATCH] bcm2835-dma: Advertise the full DMA range
+
+Unless the DMA mask is set wider than 32 bits, DMA mapping will use a
+bounce buffer.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/dma/bcm2835-dma.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/dma/bcm2835-dma.c
++++ b/drivers/dma/bcm2835-dma.c
+@@ -41,6 +41,7 @@
+ #define BCM2711_DMA_MEMCPY_CHAN 14
+ struct bcm2835_dma_cfg_data {
++      u64     dma_mask;
+       u32     chan_40bit_mask;
+ };
+@@ -302,10 +303,12 @@ DEFINE_SPINLOCK(memcpy_lock);
+ static const struct bcm2835_dma_cfg_data bcm2835_dma_cfg = {
+       .chan_40bit_mask = 0,
++      .dma_mask = DMA_BIT_MASK(32),
+ };
+ static const struct bcm2835_dma_cfg_data bcm2711_dma_cfg = {
+       .chan_40bit_mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
++      .dma_mask = DMA_BIT_MASK(36),
+ };
+ static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
+@@ -1185,6 +1188,8 @@ static struct dma_chan *bcm2835_dma_xlat
+ static int bcm2835_dma_probe(struct platform_device *pdev)
+ {
++      const struct bcm2835_dma_cfg_data *cfg_data;
++      const struct of_device_id *of_id;
+       struct bcm2835_dmadev *od;
+       struct resource *res;
+       void __iomem *base;
+@@ -1194,13 +1199,20 @@ static int bcm2835_dma_probe(struct plat
+       int irq_flags;
+       uint32_t chans_available;
+       char chan_name[BCM2835_DMA_CHAN_NAME_SIZE];
+-      const struct of_device_id *of_id;
+       int chan_count, chan_start, chan_end;
++      of_id = of_match_node(bcm2835_dma_of_match, pdev->dev.of_node);
++      if (!of_id) {
++              dev_err(&pdev->dev, "Failed to match compatible string\n");
++              return -EINVAL;
++      }
++
++      cfg_data = of_id->data;
++
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+-      rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
++      rc = dma_set_mask_and_coherent(&pdev->dev, cfg_data->dma_mask);
+       if (rc) {
+               dev_err(&pdev->dev, "Unable to set DMA mask\n");
+               return rc;
+@@ -1266,7 +1278,7 @@ static int bcm2835_dma_probe(struct plat
+               return -EINVAL;
+       }
+-      od->cfg_data = of_id->data;
++      od->cfg_data = cfg_data;
+       /* Request DMA channel mask from device tree */
+       if (of_property_read_u32(pdev->dev.of_node,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0925-ARM-dts-Add-UART-skip-init-properties-for-U-boot.patch b/target/linux/bcm27xx/patches-5.4/950-0925-ARM-dts-Add-UART-skip-init-properties-for-U-boot.patch
new file mode 100644 (file)
index 0000000..be6c9dd
--- /dev/null
@@ -0,0 +1,35 @@
+From 197b4fbd218a0a12573cdfcb011eeb3f00765d96 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 17 Jul 2020 11:20:07 +0100
+Subject: [PATCH] ARM: dts: Add UART skip-init properties for U-boot
+
+U-boot can get stuck trying to initialise UARTs that aren't mapped
+to the pin header. There is no reason for U-boot not to rely on the
+initialisation by the firmware, so tag both UARTs with the u-boot
+magic boolean property "skip-init".
+
+See: https://github.com/raspberrypi/linux/pull/3731
+     https://lists.denx.de/pipermail/u-boot/2017-April/285606.html
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm270x-rpi.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm270x-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm270x-rpi.dtsi
+@@ -102,6 +102,14 @@
+       };
+ };
++&uart0 {
++      skip-init;
++};
++
++&uart1 {
++      skip-init;
++};
++
+ &txp {
+       status = "disabled";
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0926-drm-vc4-Remove-UIF-from-the-list-of-modifiers-return.patch b/target/linux/bcm27xx/patches-5.4/950-0926-drm-vc4-Remove-UIF-from-the-list-of-modifiers-return.patch
new file mode 100644 (file)
index 0000000..7ae22a7
--- /dev/null
@@ -0,0 +1,29 @@
+From 132454781a30f57ccb393443209def76dc0b572a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 28 Jul 2020 13:01:42 +0100
+Subject: [PATCH] drm/vc4: Remove UIF from the list of modifiers
+ returned by format_mod_supported
+
+FKMS was listing UIF in the supported modifiers from format_mod_supported
+when actually the pipeline doesn't support it. X was then choosing to
+use it, and that then failed to render.
+
+Remove references to UIF.
+
+https://github.com/raspberrypi/linux/issues/3665
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -718,7 +718,6 @@ static bool vc4_fkms_format_mod_supporte
+               switch (modifier) {
+               case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+               case DRM_FORMAT_MOD_LINEAR:
+-              case DRM_FORMAT_MOD_BROADCOM_UIF:
+                       return true;
+               default:
+                       return false;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0927-ARM-proc-v7-Force-misalignment-of-early-stmia.patch b/target/linux/bcm27xx/patches-5.4/950-0927-ARM-proc-v7-Force-misalignment-of-early-stmia.patch
new file mode 100644 (file)
index 0000000..158ff69
--- /dev/null
@@ -0,0 +1,60 @@
+From 965cce6b1c6acc25d7cfd29ccf95c8ebbf1d7f57 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 29 Jul 2020 13:47:55 +0100
+Subject: [PATCH] ARM: proc-v7: Force misalignment of early stmia
+
+In an attempt to prevent the problem of CPUn not starting, explicitly
+misalign the scratch space used to save registers acros the cache
+invalidation.
+
+Notes:
+At this stage in the boot process the core is running with its cache
+disabled. Before enabling the cache its contents must be explicitly
+invalidated, a process that requires quite a few registers that the
+caller must preserve. Evidence suggests that something is writing a
+block of zeroes over that space at a time when all other cores should
+be idle, possibly some kind of write-combiner, and the misalignment is
+designed to disrupt any write-coalescing.
+
+In truth, I don't understand why this patch works, and when the failure
+is so random it is hard to be certain that this isn't just rolling the
+dice again. One interesting test would be to change the "addeq r12, #4"s
+to "addeq r12, #0"s determine see if the offset itself is significant or
+just the additional code.
+
+See: https://github.com/Hexxeh/rpi-firmware/issues/232
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/mm/proc-v7.S | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/mm/proc-v7.S
++++ b/arch/arm/mm/proc-v7.S
+@@ -287,6 +287,8 @@ __v7_ca17mp_setup:
+       mov     r10, #0
+ 1:    adr     r0, __v7_setup_stack_ptr
+       ldr     r12, [r0]
++      tst     r12, #0x1f
++      addeq   r12, r12, #4
+       add     r12, r12, r0                    @ the local stack
+       stmia   r12, {r1-r6, lr}                @ v7_invalidate_l1 touches r0-r6
+       bl      v7_invalidate_l1
+@@ -474,6 +476,8 @@ __v7_setup:
+       adr     r0, __v7_setup_stack_ptr
+       ldr     r12, [r0]
+       add     r12, r12, r0                    @ the local stack
++      tst     r12, #0x1f
++      addeq   r12, r12, #4
+       stmia   r12, {r1-r6, lr}                @ v7_invalidate_l1 touches r0-r6
+       bl      v7_invalidate_l1
+       ldmia   r12, {r1-r6, lr}
+@@ -557,7 +561,7 @@ ENDPROC(__v7_setup)
+       .bss
+       .align  2
+ __v7_setup_stack:
+-      .space  4 * 7                           @ 7 registers
++      .space  4 * 8                           @ 7 registers + 1 spare
+       __INITDATA
diff --git a/target/linux/bcm27xx/patches-5.4/950-0928-overlays-Fix-sc16is75x-overlays-w.r.t.-serdev.patch b/target/linux/bcm27xx/patches-5.4/950-0928-overlays-Fix-sc16is75x-overlays-w.r.t.-serdev.patch
new file mode 100644 (file)
index 0000000..ed9f1e1
--- /dev/null
@@ -0,0 +1,182 @@
+From a934bc7776953d7ce8e27c2d8720de58d5ceeeef Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 30 Jul 2020 15:13:09 +0100
+Subject: [PATCH] overlays: Fix sc16is75x overlays w.r.t. serdev
+
+Enabling serdev support in rpi-5.4.y had the unintended consequence of
+making any UART device node with a subnode look like a "serdev" node,
+which prevents it from having the usual /dev/ttyXXX character device.
+Solve the problem by moving the subnode (a static clock declaration)
+into the root node.
+
+At the same time, regularise (and sometimes correct) the overlays.
+
+See: https://github.com/raspberrypi/linux/issues/3765
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ .../dts/overlays/sc16is750-i2c-overlay.dts    | 23 +++++++++-------
+ .../dts/overlays/sc16is752-i2c-overlay.dts    | 27 ++++++++++---------
+ .../dts/overlays/sc16is752-spi0-overlay.dts   | 21 +++++++++------
+ .../dts/overlays/sc16is752-spi1-overlay.dts   |  6 ++---
+ 4 files changed, 45 insertions(+), 32 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts
+@@ -13,26 +13,31 @@
+                       sc16is750: sc16is750@48 {
+                               compatible = "nxp,sc16is750";
+-                              reg = <0x48>; /* address */
++                              reg = <0x48>; /* i2c address */
+                               clocks = <&sc16is750_clk>;
+                               interrupt-parent = <&gpio>;
+                               interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
++                              gpio-controller;
+                               #gpio-cells = <2>;
+-
+-                              sc16is750_clk: sc16is750_clk {
+-                                      compatible = "fixed-clock";
+-                                      #clock-cells = <0>;
+-                                      clock-frequency = <14745600>;
+-                              };
++                              i2c-max-frequency = <400000>;
+                       };
+               };
+       };
++      fragment@1 {
++              target-path = "/";
++              __overlay__ {
++                      sc16is750_clk: sc16is750_i2c_clk@48 {
++                              compatible = "fixed-clock";
++                              #clock-cells = <0>;
++                              clock-frequency = <14745600>;
++                      };
++              };
++      };
+       __overrides__ {
+               int_pin = <&sc16is750>,"interrupts:0";
+-              addr = <&sc16is750>,"reg:0",<&sc16is750_clk>,"name";
++              addr = <&sc16is750>,"reg:0", <&sc16is750_clk>,"name";
+               xtal = <&sc16is750_clk>,"clock-frequency:0";
+       };
+-
+ };
+--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts
+@@ -5,29 +5,32 @@
+       compatible = "brcm,bcm2835";
+       fragment@0 {
+-              target = <&i2c1>;
+-
+-              frag1: __overlay__ {
++              target = <&i2c_arm>;
++              __overlay__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "okay";
+                       sc16is752: sc16is752@48 {
+                               compatible = "nxp,sc16is752";
+-                              reg = <0x48>; // i2c address
++                              reg = <0x48>; /* i2c address */
+                               clocks = <&sc16is752_clk>;
+                               interrupt-parent = <&gpio>;
+-                              interrupts = <24 0x2>; /* IRQ_TYPE_EDGE_FALLING */
++                              interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
+                               gpio-controller;
+-                              #gpio-cells = <0>;
++                              #gpio-cells = <2>;
+                               i2c-max-frequency = <400000>;
+-                              status = "okay";
++                      };
++              };
++      };
+-                              sc16is752_clk: sc16is752_clk {
+-                                      compatible = "fixed-clock";
+-                                      #clock-cells = <0>;
+-                                      clock-frequency = <14745600>;
+-                              };
++      fragment@1 {
++              target-path = "/";
++              __overlay__ {
++                      sc16is752_clk: sc16is752_i2c_clk@48 {
++                              compatible = "fixed-clock";
++                              #clock-cells = <0>;
++                              clock-frequency = <14745600>;
+                       };
+               };
+       };
+--- a/arch/arm/boot/dts/overlays/sc16is752-spi0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-spi0-overlay.dts
+@@ -17,15 +17,9 @@
+                               clocks = <&sc16is752_clk>;
+                               interrupt-parent = <&gpio>;
+                               interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
+-                              #gpio-controller;
++                              gpio-controller;
+                               #gpio-cells = <2>;
+                               spi-max-frequency = <4000000>;
+-
+-                              sc16is752_clk: sc16is752_clk {
+-                                      compatible = "fixed-clock";
+-                                      #clock-cells = <0>;
+-                                      clock-frequency = <14745600>;
+-                              };
+                       };
+               };
+       };
+@@ -37,8 +31,19 @@
+               };
+       };
++      fragment@2 {
++              target-path = "/";
++              __overlay__ {
++                      sc16is752_clk: sc16is752_spi0_0_clk {
++                              compatible = "fixed-clock";
++                              #clock-cells = <0>;
++                              clock-frequency = <14745600>;
++                      };
++              };
++      };
++
+       __overrides__ {
+               int_pin = <&sc16is752>,"interrupts:0";
+-              xtal = <&sc16is752_clk>, "clock-frequency:0";
++              xtal = <&sc16is752_clk>,"clock-frequency:0";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts
+@@ -21,7 +21,7 @@
+       fragment@1 {
+               target = <&spi1>;
+-              frag1: __overlay__ {
++              __overlay__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       pinctrl-names = "default";
+@@ -35,7 +35,7 @@
+                               clocks = <&sc16is752_clk>;
+                               interrupt-parent = <&gpio>;
+                               interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
+-                              #gpio-controller;
++                              gpio-controller;
+                               #gpio-cells = <2>;
+                               spi-max-frequency = <4000000>;
+                       };
+@@ -52,7 +52,7 @@
+       fragment@3 {
+               target-path = "/";
+               __overlay__ {
+-                      sc16is752_clk: sc16is752_spi1_clk {
++                      sc16is752_clk: sc16is752_spi1_0_clk {
+                               compatible = "fixed-clock";
+                               #clock-cells = <0>;
+                               clock-frequency = <14745600>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0929-overlays-Delete-spi0-hw-cs.patch b/target/linux/bcm27xx/patches-5.4/950-0929-overlays-Delete-spi0-hw-cs.patch
new file mode 100644 (file)
index 0000000..044a3ad
--- /dev/null
@@ -0,0 +1,87 @@
+From 9fcbc40311f8de3f7a0a27155f310ff19e150d76 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 30 Jul 2020 18:06:24 +0100
+Subject: [PATCH] overlays: Delete spi0-hw-cs
+
+The spi0-hw-cs overlay is unnecessary (and actually harmful) with the
+current kernels. Delete it, leaving a note in the README and a
+deprecation message from the firmware:
+
+    dterror: overlay 'spi0-hw-cs' is deprecated: no longer necessary
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 -
+ arch/arm/boot/dts/overlays/README             |  6 ++---
+ arch/arm/boot/dts/overlays/overlay_map.dts    |  4 +++
+ .../boot/dts/overlays/spi0-hw-cs-overlay.dts  | 26 -------------------
+ 4 files changed, 7 insertions(+), 30 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -159,7 +159,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       spi-gpio40-45.dtbo \
+       spi-rtc.dtbo \
+       spi0-cs.dtbo \
+-      spi0-hw-cs.dtbo \
+       spi1-1cs.dtbo \
+       spi1-2cs.dtbo \
+       spi1-3cs.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2346,9 +2346,9 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi0-hw-cs
+-Info:   Re-enables hardware CS/CE (chip selects) for SPI0
+-Load:   dtoverlay=spi0-hw-cs
+-Params: <None>
++Info:   This overlay has been deprecated and removed because it is no longer
++        necessary and has been seen to prevent spi0 from working.
++Load:   <Deprecated>
+ Name:   spi1-1cs
+--- a/arch/arm/boot/dts/overlays/overlay_map.dts
++++ b/arch/arm/boot/dts/overlays/overlay_map.dts
+@@ -61,6 +61,10 @@
+               deprecated = "use sdio,bus_width=1,gpios_22_25";
+       };
++      spi0-hw-cs {
++              deprecated = "no longer necessary";
++      };
++
+       spi3-1cs {
+               bcm2711;
+       };
+--- a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts
++++ /dev/null
+@@ -1,26 +0,0 @@
+-/*
+- * Device tree overlay to re-enable hardware CS for SPI0
+- */
+-
+-/dts-v1/;
+-/plugin/;
+-
+-/ {
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&spi0>;
+-              __overlay__ {
+-                      cs-gpios = <0>, <0>;
+-                      status = "okay";
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&spi0_cs_pins>;
+-              __overlay__ {
+-                      brcm,pins = <8 7>;
+-                      brcm,function = <4>; /* alt0 */
+-              };
+-      };
+-};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0930-backlight-gpio-Explicitly-set-the-direction-of-the-G.patch b/target/linux/bcm27xx/patches-5.4/950-0930-backlight-gpio-Explicitly-set-the-direction-of-the-G.patch
new file mode 100644 (file)
index 0000000..d016cda
--- /dev/null
@@ -0,0 +1,88 @@
+From aa455fdc2495cb05b65cc03cc472de43df632c5c Mon Sep 17 00:00:00 2001
+From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Date: Tue, 22 Oct 2019 10:36:24 +0200
+Subject: [PATCH] backlight: gpio: Explicitly set the direction of
+ the GPIO
+
+commit 706dc68102bc7421a9e6573d149ab6d769d71cc7 upstream.
+
+The GPIO backlight driver currently requests the line 'as is', without
+acively setting its direction. This can lead to problems: if the line
+is in input mode by default, we won't be able to drive it later when
+updating the status and also reading its initial value doesn't make
+sense for backlight setting.
+
+Request the line 'as is' initially, so that we can read its value
+without affecting it but then change the direction to output explicitly
+when setting the initial brightness.
+
+Also: check the current direction and only read the value if it's output.
+
+Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ drivers/video/backlight/gpio_backlight.c | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+--- a/drivers/video/backlight/gpio_backlight.c
++++ b/drivers/video/backlight/gpio_backlight.c
+@@ -26,9 +26,8 @@ struct gpio_backlight {
+       int def_value;
+ };
+-static int gpio_backlight_update_status(struct backlight_device *bl)
++static int gpio_backlight_get_next_brightness(struct backlight_device *bl)
+ {
+-      struct gpio_backlight *gbl = bl_get_data(bl);
+       int brightness = bl->props.brightness;
+       if (bl->props.power != FB_BLANK_UNBLANK ||
+@@ -36,6 +35,14 @@ static int gpio_backlight_update_status(
+           bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+               brightness = 0;
++      return brightness;
++}
++
++static int gpio_backlight_update_status(struct backlight_device *bl)
++{
++      struct gpio_backlight *gbl = bl_get_data(bl);
++      int brightness = gpio_backlight_get_next_brightness(bl);
++
+       gpiod_set_value_cansleep(gbl->gpiod, brightness);
+       return 0;
+@@ -86,7 +93,8 @@ static int gpio_backlight_initial_power_
+               return gbl->def_value ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+       /* if the enable GPIO is disabled, do not enable the backlight */
+-      if (gpiod_get_value_cansleep(gbl->gpiod) == 0)
++      if (gpiod_get_direction(gbl->gpiod) == 0 &&
++          gpiod_get_value_cansleep(gbl->gpiod) == 0)
+               return FB_BLANK_POWERDOWN;
+       return FB_BLANK_UNBLANK;
+@@ -100,7 +108,7 @@ static int gpio_backlight_probe(struct p
+       struct backlight_properties props;
+       struct backlight_device *bl;
+       struct gpio_backlight *gbl;
+-      int ret;
++      int ret, init_brightness;
+       gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL);
+       if (gbl == NULL)
+@@ -153,7 +161,12 @@ static int gpio_backlight_probe(struct p
+       bl->props.power = gpio_backlight_initial_power_state(gbl);
+       bl->props.brightness = 1;
+-      backlight_update_status(bl);
++      init_brightness = gpio_backlight_get_next_brightness(bl);
++      ret = gpiod_direction_output(gbl->gpiod, init_brightness);
++      if (ret) {
++              dev_err(&pdev->dev, "failed to set initial brightness\n");
++              return ret;
++      }
+       platform_set_drvdata(pdev, bl);
+       return 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0931-overlays-Add-maxtherm-overlay-for-MAX6675-31855.patch b/target/linux/bcm27xx/patches-5.4/950-0931-overlays-Add-maxtherm-overlay-for-MAX6675-31855.patch
new file mode 100644 (file)
index 0000000..882cb8d
--- /dev/null
@@ -0,0 +1,238 @@
+From 56e726d1631c9551530b8db4127352c64c3cb94d Mon Sep 17 00:00:00 2001
+From: Dougie Lawson <dl1ims@gmail.com>
+Date: Mon, 27 Jul 2020 23:52:40 +0100
+Subject: [PATCH] overlays: Add maxtherm overlay for MAX6675/31855
+
+Add an overlay - maxtherm - to support the MAX6675 and MAX31855 family
+of thermocouples.
+
+Developed from an original set of overlays by Dougie Lawson.
+
+See: https://github.com/raspberrypi/linux/pull/3763
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  30 ++++
+ .../boot/dts/overlays/maxtherm-overlay.dts    | 166 ++++++++++++++++++
+ 3 files changed, 197 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/maxtherm-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -98,6 +98,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       justboom-digi.dtbo \
+       ltc294x.dtbo \
+       max98357a.dtbo \
++      maxtherm.dtbo \
+       mbed-dac.dtbo \
+       mcp23017.dtbo \
+       mcp23s17.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1622,6 +1622,36 @@ Params: no-sdmode               Driver d
+                                 of the DAC (default GPIO4 if parameter omitted).
++Name:   maxtherm
++Info:   Configure a MAX6675 or MAX31855 thermocouple as an IIO device.
++
++        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 overlay expects to disable the relevant spidev node, so also using
++        e.g. cs0_spidev=off is unnecessary.
++
++        Note:   with the 5.7 kernel (and later) there will also be
++                overlays for MAX31855E, MAX31855J, MAX31855K,
++                MAX31885N, MAX31855R, MAX31855S and MAX31855T.
++
++        Example:
++        MAX31855 on /dev/spidev0.0
++            dtoverlay=maxtherm,spi0-0,max31855
++
++Load:   dtoverlay=maxtherm,<param>=<val>
++Params: spi<n>-<m>              Configure device at spi<n>, cs<m>
++                                (boolean, required)
++        max6675                 Enable support for the MAX6675 (default)
++        max31855                Enable support for the MAX31855
++        max31855e               Enable support for the MAX31855E
++        max31855j               Enable support for the MAX31855J
++        max31855k               Enable support for the MAX31855K
++        max31855n               Enable support for the MAX31855N
++        max31855r               Enable support for the MAX31855R
++        max31855s               Enable support for the MAX31855S
++        max31855t               Enable support for the MAX31855T
++
++
+ Name:   mbed-dac
+ Info:   Configures the mbed AudioCODEC (TLV320AIC23B)
+ Load:   dtoverlay=mbed-dac
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/maxtherm-overlay.dts
+@@ -0,0 +1,166 @@
++/*
++ * Universal device tree overlay for SPI devices
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spidev0>;
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@1 {
++              target = <&spidev1>;
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@2 {
++              target-path = "spi1/spidev@0";
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@3 {
++              target-path = "spi1/spidev@1";
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@4 {
++              target-path = "spi1/spidev@2";
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@5 {
++              target-path = "spi2/spidev@0";
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@6 {
++              target-path = "spi2/spidev@1";
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@7 {
++              target-path = "spi2/spidev@2";
++              __dormant__ {
++                      status = "disabled";
++              };
++      };
++
++      maxfrag: fragment@8 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      max: maxtherm@0 {
++                              compatible = "maxim,max6675";
++                              reg = <0>;
++                              spi-max-frequency = <500000>;
++                      };
++              };
++      };
++
++      fragment@9 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855e", "maxim,max31855";
++              };
++      };
++
++      fragment@10 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855j", "maxim,max31855";
++              };
++      };
++
++      fragment@11 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855k", "maxim,max31855";
++              };
++      };
++
++      fragment@12 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855n", "maxim,max31855";
++              };
++      };
++
++      fragment@13 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855r", "maxim,max31855";
++              };
++      };
++
++      fragment@14 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855s", "maxim,max31855";
++              };
++      };
++
++      fragment@15 {
++              target = <&max>;
++              __dormant__ {
++                      compatible = "maxim,max31855t", "maxim,max31855";
++              };
++      };
++
++      __overrides__ {
++              spi0-0 = <0>, "+0",
++                       <&maxfrag>,"target:0=",<&spi0>,
++                       <&max>,"reg:0=0";
++              spi0-1 = <0>, "+1",
++                       <&maxfrag>,"target:0=",<&spi0>,
++                       <&max>,"reg:0=1";
++              spi1-0 = <0>, "+2",
++                       <&maxfrag>,"target:0=",<&spi1>,
++                       <&max>,"reg:0=0";
++              spi1-1 = <0>, "+3",
++                       <&maxfrag>,"target:0=",<&spi1>,
++                       <&max>,"reg:0=1";
++              spi1-2 = <0>, "+4",
++                       <&maxfrag>,"target:0=",<&spi1>,
++                       <&max>,"reg:0=2";
++              spi2-0 = <0>, "+5",
++                       <&maxfrag>,"target:0=",<&spi2>,
++                       <&max>,"reg:0=0";
++              spi2-1 = <0>, "+6",
++                       <&maxfrag>,"target:0=",<&spi2>,
++                       <&max>,"reg:0=1";
++              spi2-2 = <0>, "+7",
++                       <&maxfrag>,"target:0=",<&spi2>,
++                       <&max>,"reg:0=2";
++              max6675 = <&max>,"compatible=maxim,max6675";
++              max31855 = <&max>,"compatible=maxim,max31855";
++              max31855e = <0>,"+9";
++              max31855j = <0>,"+10";
++              max31855k = <0>,"+11";
++              max31855n = <0>,"+12";
++              max31855r = <0>,"+13";
++              max31855s = <0>,"+14";
++              max31855t = <0>,"+15";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0932-dtoverlays-Add-the-iio_hwmon-driver-to-correct-ADC-i.patch b/target/linux/bcm27xx/patches-5.4/950-0932-dtoverlays-Add-the-iio_hwmon-driver-to-correct-ADC-i.patch
new file mode 100644 (file)
index 0000000..1005396
--- /dev/null
@@ -0,0 +1,40 @@
+From 8bfdbba339bd363633e2232777fd749000011a41 Mon Sep 17 00:00:00 2001
+From: Annaliese McDermond <nh6z@nh6z.net>
+Date: Sun, 2 Aug 2020 18:25:07 +0000
+Subject: [PATCH] dtoverlays: Add the iio_hwmon driver to correct ADC
+ issues
+
+The Linux kernel maintainers removed the hwmon driver for the
+ads1015 used on this board.  They deprecated it in favor of using
+the IIO version of the driver with the iio_hwmon bridge.  This
+patch updates the DRAWS dtoverlay to support that usage.
+
+Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
+---
+ arch/arm/boot/dts/overlays/draws-overlay.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/draws-overlay.dts
++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts
+@@ -45,6 +45,13 @@
+                 gpios = <&gpio 7 0>;
+                 status = "okay";
+             };
++
++            iio-hwmon {
++                compatible = "iio-hwmon";
++                status = "okay";
++                io-channels = <&tla2024 4>, <&tla2024 5>, <&tla2024 6>,
++                              <&tla2024 7>;
++            };
+         };
+     };
+@@ -91,6 +98,7 @@
+                 reg = <0x48>;
+                 #address-cells = <1>;
+                 #size-cells = <0>;
++                #io-channel-cells = <1>;
+                 adc_ch4: channel@4 {
+                     reg = <4>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0933-dts-bcm2711-Disable-DVP-by-default.patch b/target/linux/bcm27xx/patches-5.4/950-0933-dts-bcm2711-Disable-DVP-by-default.patch
new file mode 100644 (file)
index 0000000..9e4612e
--- /dev/null
@@ -0,0 +1,44 @@
+From c74f523a5af1d9d3a6f9aee05585e52a78a79f53 Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.com>
+Date: Fri, 7 Aug 2020 13:55:18 +0100
+Subject: [PATCH] dts: bcm2711: Disable DVP by default
+
+The HDMI DVP should be disabled by default as is the case for other
+display related drivers. This changes resolves an issue when using
+the legacy firmware display driver where the DVP caused the 108 MHz
+clock in HDMI TX to be gated off when Linux started. This effectively
+stopped the firmware from being able to change the HDMI analog PHY
+registers.
+
+Add a fragment to re-enable this in vc4-kms-v3d-pi4-overlay
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi                     | 1 +
+ arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -46,6 +46,7 @@
+                       clocks = <&clk_108MHz>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
++                      status = "disabled";
+               };
+               hdmi0: hdmi@7ef00700 {
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts
+@@ -145,6 +145,13 @@
+               };
+       };
++      fragment@20 {
++              target = <&dvp>;
++              __overlay__  {
++                      status = "okay";
++              };
++      };
++
+       __overrides__ {
+               audio   = <0>,"!17";
+               audio1   = <0>,"!18";
diff --git a/target/linux/bcm27xx/patches-5.4/950-0934-ARM-dts-Add-required-USB-power-domain-for-XCHI.patch b/target/linux/bcm27xx/patches-5.4/950-0934-ARM-dts-Add-required-USB-power-domain-for-XCHI.patch
new file mode 100644 (file)
index 0000000..28cb8e7
--- /dev/null
@@ -0,0 +1,24 @@
+From 0ce033a8b915cd72b002505dd7b7ff90c36def02 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 5 Aug 2020 17:35:48 +0100
+Subject: [PATCH] ARM: dts: Add required USB power domain for XCHI
+
+The firmware setting otg_mode=1 can be used to enable the onboard XHCI
+controller in host mode, but that requires that the USB power domain
+is enabled.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -217,6 +217,7 @@
+               status = "disabled";
+               reg = <0x0 0x7e9c0000  0x0 0x100000>;
+               interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
++              power-domains = <&power RPI_POWER_DOMAIN_USB>;
+       };
+       hevc-decoder@7eb00000 {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0935-overlays-Regenerate-upstream-pi4.patch b/target/linux/bcm27xx/patches-5.4/950-0935-overlays-Regenerate-upstream-pi4.patch
new file mode 100644 (file)
index 0000000..4293909
--- /dev/null
@@ -0,0 +1,28 @@
+From a5dd8f7ddc00f0f4e58f56b729b7e0066edf4e71 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 12 Aug 2020 10:15:52 +0100
+Subject: [PATCH] overlays: Regenerate upstream-pi4
+
+The recent modification to vc4-kms-v3d-pi4 also results in a change
+to the Pi 4 version of the upstream overlay.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
+@@ -128,6 +128,12 @@
+               };
+       };
+       fragment@20 {
++              target = <&dvp>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++      fragment@21 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0936-drm-vc4-Increase-the-number-of-planes-per-crtc-in-FK.patch b/target/linux/bcm27xx/patches-5.4/950-0936-drm-vc4-Increase-the-number-of-planes-per-crtc-in-FK.patch
new file mode 100644 (file)
index 0000000..b2b1e7f
--- /dev/null
@@ -0,0 +1,105 @@
+From 078e6dfcff1fc4ef0ee3b29a5f94403624c2e7ac Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Mon, 20 Jul 2020 16:42:57 +0100
+Subject: [PATCH] drm/vc4: Increase the number of planes per crtc in
+ FKMS.
+
+The number assigned was arbitrary as one primary, one overlay,
+and one cursor.
+The number has to be below the DRM limit of 32 planes total,
+and the current firmware API limit of 16 planes total.
+
+Increase the number to 8 planes per crtc (1 primary,
+6 overlay, and a cursor).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 54 ++++++++++----------------
+ 1 file changed, 21 insertions(+), 33 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -48,7 +48,7 @@ struct vc4_fkms {
+       bool bcm2711;
+ };
+-#define PLANES_PER_CRTC               3
++#define PLANES_PER_CRTC               8
+ struct set_plane {
+       u8 display;
+@@ -1742,7 +1742,6 @@ static int vc4_fkms_create_screen(struct
+       struct vc4_crtc *vc4_crtc;
+       struct vc4_fkms_encoder *vc4_encoder;
+       struct drm_crtc *crtc;
+-      struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
+       struct drm_plane *destroy_plane, *temp;
+       struct mailbox_blank_display blank = {
+               .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
+@@ -1750,7 +1749,8 @@ static int vc4_fkms_create_screen(struct
+               .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, },
+               .blank = 1,
+       };
+-      int ret;
++      struct drm_plane *planes[PLANES_PER_CRTC];
++      int ret, i;
+       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+       if (!vc4_crtc)
+@@ -1763,38 +1763,26 @@ static int vc4_fkms_create_screen(struct
+       /* Blank the firmware provided framebuffer */
+       rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
+-      primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
+-                                          display_ref,
+-                                          0 + (display_idx * PLANES_PER_CRTC)
+-                                         );
+-      if (IS_ERR(primary_plane)) {
+-              dev_err(dev, "failed to construct primary plane\n");
+-              ret = PTR_ERR(primary_plane);
+-              goto err;
+-      }
+-
+-      overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
+-                                          display_ref,
+-                                          1 + (display_idx * PLANES_PER_CRTC)
+-                                         );
+-      if (IS_ERR(overlay_plane)) {
+-              dev_err(dev, "failed to construct overlay plane\n");
+-              ret = PTR_ERR(overlay_plane);
+-              goto err;
+-      }
+-
+-      cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
+-                                         display_ref,
+-                                         2 + (display_idx * PLANES_PER_CRTC)
+-                                        );
+-      if (IS_ERR(cursor_plane)) {
+-              dev_err(dev, "failed to construct cursor plane\n");
+-              ret = PTR_ERR(cursor_plane);
+-              goto err;
++      for (i = 0; i < PLANES_PER_CRTC; i++) {
++              planes[i] = vc4_fkms_plane_init(drm,
++                                              (i == 0) ?
++                                                DRM_PLANE_TYPE_PRIMARY :
++                                                (i == PLANES_PER_CRTC - 1) ?
++                                                      DRM_PLANE_TYPE_CURSOR :
++                                                      DRM_PLANE_TYPE_OVERLAY,
++                                              display_ref,
++                                              i + (display_idx * PLANES_PER_CRTC)
++                                             );
++              if (IS_ERR(planes[i])) {
++                      dev_err(dev, "failed to construct plane %u\n", i);
++                      ret = PTR_ERR(planes[i]);
++                      goto err;
++              }
+       }
+-      drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
+-                                &vc4_crtc_funcs, NULL);
++      drm_crtc_init_with_planes(drm, crtc, planes[0],
++                                planes[PLANES_PER_CRTC - 1], &vc4_crtc_funcs,
++                                NULL);
+       drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
+       vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0937-drm-vc4-Set-the-possible-crtcs-mask-correctly-for-pl.patch b/target/linux/bcm27xx/patches-5.4/950-0937-drm-vc4-Set-the-possible-crtcs-mask-correctly-for-pl.patch
new file mode 100644 (file)
index 0000000..9f020f7
--- /dev/null
@@ -0,0 +1,40 @@
+From 84a67330f3457469bc42f203111fc5ad800c506b Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 13 Aug 2020 18:29:56 +0100
+Subject: [PATCH] drm/vc4: Set the possible crtcs mask correctly for
+ planes with FKMS
+
+The driver was assigning all planes to crtcs when actually they're
+mapped to a specific crtc.
+
+Correct the mask.
+
+https://github.com/raspberrypi/linux/issues/3734
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -816,7 +816,7 @@ static struct drm_plane *vc4_fkms_plane_
+               formats[num_formats++] = vc_image_formats[i].drm;
+       plane = &vc4_plane->base;
+-      ret = drm_universal_plane_init(dev, plane, 0xff,
++      ret = drm_universal_plane_init(dev, plane, 0,
+                                      &vc4_plane_funcs,
+                                      formats, num_formats, modifiers,
+                                      type, NULL);
+@@ -1785,6 +1785,10 @@ static int vc4_fkms_create_screen(struct
+                                 NULL);
+       drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
++      /* Update the possible_crtcs mask for the overlay plane(s) */
++      for (i = 1; i < (PLANES_PER_CRTC - 1); i++)
++              planes[i]->possible_crtcs = drm_crtc_mask(crtc);
++
+       vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
+       if (!vc4_encoder)
+               return -ENOMEM;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0938-staging-vc04_services-codec-Fix-incorrect-buffer-cle.patch b/target/linux/bcm27xx/patches-5.4/950-0938-staging-vc04_services-codec-Fix-incorrect-buffer-cle.patch
new file mode 100644 (file)
index 0000000..14736dc
--- /dev/null
@@ -0,0 +1,52 @@
+From 84fa15b87a5f938c064ee2d9fca43248865ffbec Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 13 Aug 2020 16:58:18 +0100
+Subject: [PATCH] staging: vc04_services: codec: Fix incorrect buffer
+ cleanup
+
+The allocated input and output buffers are initialised in
+buf_init and should only be cleared up in buf_cleanup.
+stop_streaming was (incorrectly) cleaning up the buffers to
+avoid an issue in videobuf2 that had been fixed by the orphaned
+buffer support.
+
+Remove the erroneous cleanup.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c          | 17 +----------------
+ 1 file changed, 1 insertion(+), 16 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2320,10 +2320,7 @@ static void bcm2835_codec_stop_streaming
+       struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
+       struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
+       struct vb2_v4l2_buffer *vbuf;
+-      struct vb2_v4l2_buffer *vb2;
+-      struct v4l2_m2m_buffer *m2m;
+-      struct m2m_mmal_buffer *buf;
+-      int ret, i;
++      int ret;
+       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
+                __func__, q->type);
+@@ -2363,18 +2360,6 @@ static void bcm2835_codec_stop_streaming
+               }
+       }
+-      /*
+-       * Release the VCSM handle here as otherwise REQBUFS(0) aborts because
+-       * someone is using the dmabuf before giving the driver a chance to do
+-       * anything about it.
+-       */
+-      for (i = 0; i < q->num_buffers; i++) {
+-              vb2 = to_vb2_v4l2_buffer(q->bufs[i]);
+-              m2m = container_of(vb2, struct v4l2_m2m_buffer, vb);
+-              buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
+-
+-              bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
+-      }
+       /* If both ports disabled, then disable the component */
+       if (!ctx->component->input[0].enabled &&
diff --git a/target/linux/bcm27xx/patches-5.4/950-0939-staging-vc04_service-codec-Allow-start_streaming-to-.patch b/target/linux/bcm27xx/patches-5.4/950-0939-staging-vc04_service-codec-Allow-start_streaming-to-.patch
new file mode 100644 (file)
index 0000000..66a551d
--- /dev/null
@@ -0,0 +1,70 @@
+From d88ef7d22cac032c4ddf7e4b8af5982d5a3019cb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 13 Aug 2020 17:01:27 +0100
+Subject: [PATCH] staging: vc04_service: codec: Allow start_streaming
+ to update the buffernum
+
+start_streaming passes a count of how many buffers have been queued
+to videobuf2.
+
+Allow this value to update the number of buffers the VPU allocates
+on a port to avoid buffer recycling issues.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c        | 23 +++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2268,6 +2268,7 @@ static int bcm2835_codec_start_streaming
+       struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
+       struct bcm2835_codec_dev *dev = ctx->dev;
+       struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
++      struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
+       int ret;
+       v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
+@@ -2283,6 +2284,20 @@ static int bcm2835_codec_start_streaming
+               ctx->component_enabled = true;
+       }
++      if (count < port->minimum_buffer.num)
++              count = port->minimum_buffer.num;
++
++      if (port->current_buffer.num != count + 1) {
++              v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, buffer count changed %u to %u\n",
++                       __func__, ctx, port->current_buffer.num, count + 1);
++
++              port->current_buffer.num = count + 1;
++              ret = vchiq_mmal_port_set_format(dev->instance, port);
++              if (ret)
++                      v4l2_err(&ctx->dev->v4l2_dev, "%s: Error updating buffer count, ret %d\n",
++                               __func__, ret);
++      }
++
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /*
+                * Create the EOS buffer.
+@@ -2294,17 +2309,17 @@ static int bcm2835_codec_start_streaming
+                                     &q_data->eos_buffer.mmal);
+               q_data->eos_buffer_in_use = false;
+-              ctx->component->input[0].cb_ctx = ctx;
++              port->cb_ctx = ctx;
+               ret = vchiq_mmal_port_enable(dev->instance,
+-                                           &ctx->component->input[0],
++                                           port,
+                                            ip_buffer_cb);
+               if (ret)
+                       v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
+                                __func__, ret);
+       } else {
+-              ctx->component->output[0].cb_ctx = ctx;
++              port->cb_ctx = ctx;
+               ret = vchiq_mmal_port_enable(dev->instance,
+-                                           &ctx->component->output[0],
++                                           port,
+                                            op_buffer_cb);
+               if (ret)
+                       v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
diff --git a/target/linux/bcm27xx/patches-5.4/950-0940-staging-vc04_services-codec-Fix-component-enable-dis.patch b/target/linux/bcm27xx/patches-5.4/950-0940-staging-vc04_services-codec-Fix-component-enable-dis.patch
new file mode 100644 (file)
index 0000000..16c1cd7
--- /dev/null
@@ -0,0 +1,38 @@
+From 764c8052ce21a56a55dc25dbc6ee0c075952cdeb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 13 Aug 2020 17:04:53 +0100
+Subject: [PATCH] staging: vc04_services: codec: Fix component
+ enable/disable
+
+start_streaming enabled the VPU component if ctx->component_enabled
+was not set.
+stop_streaming disabled the VPU component if both ports were
+disabled. It didn't clear ctx->component_enabled.
+
+If seeking, this meant that the component never got re-enabled,
+and buffers never got processed afterwards.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c  | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2377,13 +2377,15 @@ static void bcm2835_codec_stop_streaming
+       /* If both ports disabled, then disable the component */
+-      if (!ctx->component->input[0].enabled &&
++      if (ctx->component_enabled &&
++          !ctx->component->input[0].enabled &&
+           !ctx->component->output[0].enabled) {
+               ret = vchiq_mmal_component_disable(dev->instance,
+                                                  ctx->component);
+               if (ret)
+                       v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
+                                __func__, ret);
++              ctx->component_enabled = false;
+       }
+       if (V4L2_TYPE_IS_OUTPUT(q->type))
diff --git a/target/linux/bcm27xx/patches-5.4/950-0941-update-rpi-display-overlay.dts-pins-for-5.4.patch b/target/linux/bcm27xx/patches-5.4/950-0941-update-rpi-display-overlay.dts-pins-for-5.4.patch
new file mode 100644 (file)
index 0000000..eed665b
--- /dev/null
@@ -0,0 +1,32 @@
+From 6d2723af0ade644e99e069b54dbcac8b58d603f2 Mon Sep 17 00:00:00 2001
+From: Andreas Watterott <1488433+awatterott@users.noreply.github.com>
+Date: Mon, 17 Aug 2020 21:17:09 +0200
+Subject: [PATCH] update rpi-display-overlay.dts pins for 5.4
+
+---
+ arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
++++ b/arch/arm/boot/dts/overlays/rpi-display-overlay.dts
+@@ -59,9 +59,9 @@
+                               bgr;
+                               fps = <30>;
+                               buswidth = <8>;
+-                              reset-gpios = <&gpio 23 0>;
++                              reset-gpios = <&gpio 23 1>;
+                               dc-gpios = <&gpio 24 0>;
+-                              led-gpios = <&gpio 18 1>;
++                              led-gpios = <&gpio 18 0>;
+                               debug = <0>;
+                       };
+@@ -72,7 +72,7 @@
+                               spi-max-frequency = <2000000>;
+                               interrupts = <25 2>; /* high-to-low edge triggered */
+                               interrupt-parent = <&gpio>;
+-                              pendown-gpio = <&gpio 25 0>;
++                              pendown-gpio = <&gpio 25 1>;
+                               ti,x-plate-ohms = /bits/ 16 <60>;
+                               ti,pressure-max = /bits/ 16 <255>;
+                       };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0942-Bluetooth-btrtl-Add-support-for-RTL8761B.patch b/target/linux/bcm27xx/patches-5.4/950-0942-Bluetooth-btrtl-Add-support-for-RTL8761B.patch
new file mode 100644 (file)
index 0000000..f0fbdd4
--- /dev/null
@@ -0,0 +1,77 @@
+From 61695e30db3121c11e52be89751e610d2e97212a Mon Sep 17 00:00:00 2001
+From: "Ziqian SUN (Zamir)" <sztsian@gmail.com>
+Date: Sat, 11 Apr 2020 09:34:27 +0800
+Subject: [PATCH] Bluetooth: btrtl: Add support for RTL8761B
+
+commit 04896832c94aae4842100cafb8d3a73e1bed3a45 upstream.
+
+Add new compatible device RTL8761B. RTL8761B is a USB Bluetooth device,
+with support of BLE and BR/EDR. The USB info is
+
+T:  Bus=03 Lev=04 Prnt=04 Port=00 Cnt=01 Dev#= 29 Spd=12   MxCh= 0
+D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
+P:  Vendor=0bda ProdID=8771 Rev= 2.00
+S:  Manufacturer=Realtek
+S:  Product=Bluetooth Radio
+S:  SerialNumber=XXXXXXXXXXXX
+C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=1ms
+E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
+E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
+I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
+I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
+I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
+I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
+I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
+E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
+
+Signed-off-by: Ziqian SUN (Zamir) <sztsian@gmail.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+ drivers/bluetooth/btrtl.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/bluetooth/btrtl.c
++++ b/drivers/bluetooth/btrtl.c
+@@ -130,12 +130,19 @@ static const struct id_table ic_id_table
+         .cfg_name = "rtl_bt/rtl8821c_config" },
+       /* 8761A */
+-      { IC_MATCH_FL_LMPSUBV, RTL_ROM_LMP_8761A, 0x0,
++      { IC_INFO(RTL_ROM_LMP_8761A, 0xa),
+         .config_needed = false,
+         .has_rom_version = true,
+         .fw_name  = "rtl_bt/rtl8761a_fw.bin",
+         .cfg_name = "rtl_bt/rtl8761a_config" },
++      /* 8761B */
++      { IC_INFO(RTL_ROM_LMP_8761A, 0xb),
++        .config_needed = false,
++        .has_rom_version = true,
++        .fw_name  = "rtl_bt/rtl8761b_fw.bin",
++        .cfg_name = "rtl_bt/rtl8761b_config" },
++
+       /* 8822C with USB interface */
+       { IC_INFO(RTL_ROM_LMP_8822B, 0xc),
+         .config_needed = false,
+@@ -255,6 +262,7 @@ static int rtlbt_parse_firmware(struct h
+               { RTL_ROM_LMP_8723B, 9 },       /* 8723D */
+               { RTL_ROM_LMP_8821A, 10 },      /* 8821C */
+               { RTL_ROM_LMP_8822B, 13 },      /* 8822C */
++              { RTL_ROM_LMP_8761A, 14 },      /* 8761B */
+       };
+       min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0943-dtoverlays-Add-overlay-for-the-PCA953x-family-of-GPI.patch b/target/linux/bcm27xx/patches-5.4/950-0943-dtoverlays-Add-overlay-for-the-PCA953x-family-of-GPI.patch
new file mode 100644 (file)
index 0000000..181440c
--- /dev/null
@@ -0,0 +1,315 @@
+From 5a7c48622a4f7665039211414c9fe4a1914ae3eb Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Mon, 17 Aug 2020 18:11:47 +0100
+Subject: [PATCH] dtoverlays: Add overlay for the PCA953x family of
+ GPIO expanders
+
+Adds an overlay for configuring all the GPIO expanders supported
+by the driver under GPIO_PCA953X.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  36 +++
+ .../arm/boot/dts/overlays/pca953x-overlay.dts | 240 ++++++++++++++++++
+ 3 files changed, 277 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/pca953x-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -119,6 +119,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       ov7251.dtbo \
+       ov9281.dtbo \
+       papirus.dtbo \
++      pca953x.dtbo \
+       pibell.dtbo \
+       piglow.dtbo \
+       piscreen.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1873,6 +1873,42 @@ Params: panel                   Display
+         speed                   Display SPI bus speed
++Name:   pca953x
++Info:   TI PCA953x family of I2C GPIO expanders. Default is for NXP PCA9534.
++Load:   dtoverlay=pca953x,<param>=<val>
++Params: addr                    I2C address of expander. Default 0x20.
++        pca6416                 Select the NXP PCA6416 (16 bit)
++        pca9505                 Select the NXP PCA9505 (40 bit)
++        pca9535                 Select the NXP PCA9535 (16 bit)
++        pca9536                 Select the NXP PCA9536 or TI PCA9536 (4 bit)
++        pca9537                 Select the NXP PCA9537 (4 bit)
++        pca9538                 Select the NXP PCA9538 (8 bit)
++        pca9539                 Select the NXP PCA9539 (16 bit)
++        pca9554                 Select the NXP PCA9554 (8 bit)
++        pca9555                 Select the NXP PCA9555 (16 bit)
++        pca9556                 Select the NXP PCA9556 (8 bit)
++        pca9557                 Select the NXP PCA9557 (8 bit)
++        pca9574                 Select the NXP PCA9574 (8 bit)
++        pca9575                 Select the NXP PCA9575 (16 bit)
++        pca9698                 Select the NXP PCA9698 (40 bit)
++        pca16416                Select the NXP PCA16416 (16 bit)
++        pca16524                Select the NXP PCA16524 (24 bit)
++        pca19555a               Select the NXP PCA19555A (16 bit)
++        max7310                 Select the Maxim MAX7310 (8 bit)
++        max7312                 Select the Maxim MAX7312 (16 bit)
++        max7313                 Select the Maxim MAX7313 (16 bit)
++        max7315                 Select the Maxim MAX7315 (8 bit)
++        pca6107                 Select the TI PCA6107 (8 bit)
++        tca6408                 Select the TI TCA6408 (8 bit)
++        tca6416                 Select the TI TCA6416 (16 bit)
++        tca6424                 Select the TI TCA6424 (24 bit)
++        tca9539                 Select the TI TCA9539 (16 bit)
++        tca9554                 Select the TI TCA9554 (8 bit)
++        cat9554                 Select the Onnn CAT9554 (8 bit)
++        pca9654                 Select the Onnn PCA9654 (8 bit)
++        xra1202                 Select the Exar XRA1202 (8 bit)
++
++
+ [ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ]
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/pca953x-overlay.dts
+@@ -0,0 +1,240 @@
++// Definitions for NXP PCA953x family of I2C GPIO controllers on ARM I2C bus.
++/dts-v1/;
++/plugin/;
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2c_arm>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pca: pca@20 {
++                              compatible = "nxp,pca9534";
++                              reg = <0x20>;
++                              gpio-controller;
++                              #gpio-cells = <2>;
++
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca6416";
++              };
++      };
++      fragment@2 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9505";
++              };
++      };
++      fragment@3 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9535";
++              };
++      };
++      fragment@4 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9536";
++              };
++      };
++      fragment@5 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9537";
++              };
++      };
++      fragment@6 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9538";
++              };
++      };
++      fragment@7 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9539";
++              };
++      };
++      fragment@8 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9554";
++              };
++      };
++      fragment@9 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9555";
++              };
++      };
++      fragment@10 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9556";
++              };
++      };
++      fragment@11 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9557";
++              };
++      };
++      fragment@12 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9574";
++              };
++      };
++      fragment@13 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9575";
++              };
++      };
++      fragment@14 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca9698";
++              };
++      };
++      fragment@15 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca16416";
++              };
++      };
++      fragment@16 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca16524";
++              };
++      };
++      fragment@17 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "nxp,pca19555a";
++              };
++      };
++      fragment@18 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "maxim,max7310";
++              };
++      };
++      fragment@19 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "maxim,max7312";
++              };
++      };
++      fragment@20 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "maxim,max7313";
++              };
++      };
++      fragment@21 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "maxim,max7315";
++              };
++      };
++      fragment@22 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "ti,pca6107";
++              };
++      };
++      fragment@23 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "ti,tca6408";
++              };
++      };
++      fragment@24 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "ti,tca6416";
++              };
++      };
++      fragment@25 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "ti,tca6424";
++              };
++      };
++      fragment@26 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "ti,tca9539";
++              };
++      };
++      fragment@27 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "ti,tca9554";
++              };
++      };
++      fragment@28 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "onnn,cat9554";
++              };
++      };
++      fragment@29 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "onnn,pca9654";
++              };
++      };
++      fragment@30 {
++              target = <&pca>;
++              __dormant__ {
++                      compatible = "exar,xra1202";
++              };
++      };
++
++      __overrides__ {
++              addr = <&pca>,"reg:0";
++              pca6416 = <0>, "+1";
++              pca9505 = <0>, "+2";
++              pca9535 = <0>, "+3";
++              pca9536 = <0>, "+4";
++              pca9537 = <0>, "+5";
++              pca9538 = <0>, "+6";
++              pca9539 = <0>, "+7";
++              pca9554 = <0>, "+8";
++              pca9555 = <0>, "+9";
++              pca9556 = <0>, "+10";
++              pca9557 = <0>, "+11";
++              pca9574 = <0>, "+12";
++              pca9575 = <0>, "+13";
++              pca9698 = <0>, "+14";
++              pca16416 = <0>, "+15";
++              pca16524 = <0>, "+16";
++              pca19555a = <0>, "+17";
++              max7310 = <0>, "+18";
++              max7312 = <0>, "+19";
++              max7313 = <0>, "+20";
++              max7315 = <0>, "+21";
++              pca6107 = <0>, "+22";
++              tca6408 = <0>, "+23";
++              tca6416 = <0>, "+24";
++              tca6424 = <0>, "+25";
++              tca9539 = <0>, "+26";
++              tca9554 = <0>, "+27";
++              cat9554 = <0>, "+28";
++              pca9654 = <0>, "+29";
++              xra1202 = <0>, "+30";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0944-rtc-rv3028-Write-BSM-and-TCE-TCR-to-EEPROM.patch b/target/linux/bcm27xx/patches-5.4/950-0944-rtc-rv3028-Write-BSM-and-TCE-TCR-to-EEPROM.patch
new file mode 100644 (file)
index 0000000..54f3f4f
--- /dev/null
@@ -0,0 +1,120 @@
+From ffc137a8949cd7859bdf139fa7a56b9dbdb4b2ce Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 15 May 2020 16:28:32 +0100
+Subject: [PATCH] rtc: rv3028: Write BSM and TCE/TCR to EEPROM
+
+Periodically the RV3028 refreshes registers from the EEPROM. When this
+happens, some settings that have only been committed to registers are
+lost. Change the handling of backup-switchover-mode and
+trickle-resistor-ohms to write the EEPROM instead (if something has
+changed), on the understanding that registers will be refreshed
+afterwards.
+
+See: https://github.com/raspberrypi/linux/issues/2912
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/rtc/rtc-rv3028.c | 60 ++++++++++++++++++++++++++++------------
+ 1 file changed, 43 insertions(+), 17 deletions(-)
+
+--- a/drivers/rtc/rtc-rv3028.c
++++ b/drivers/rtc/rtc-rv3028.c
+@@ -18,6 +18,7 @@
+ #include <linux/of_device.h>
+ #include <linux/regmap.h>
+ #include <linux/rtc.h>
++//#include "rtc-core.h"
+ #define RV3028_SEC                    0x00
+ #define RV3028_MIN                    0x01
+@@ -73,7 +74,7 @@
+ #define RV3028_BACKUP_TCE             BIT(5)
+ #define RV3028_BACKUP_TCR_MASK                GENMASK(1,0)
+-#define RV3028_BACKUP_BSM_MASK                0x0C
++#define RV3028_BACKUP_BSM_MASK                GENMASK(3,2)
+ #define OFFSET_STEP_PPT                       953674
+@@ -601,7 +602,8 @@ static int rv3028_probe(struct i2c_clien
+       struct rv3028_data *rv3028;
+       int ret, status;
+       u32 ohms;
+-      u8 bsm;
++      u32 bsm;
++      u8 backup, backup_bits, backup_mask;
+       struct nvmem_config nvmem_cfg = {
+               .name = "rv3028_nvram",
+               .word_size = 1,
+@@ -673,16 +675,17 @@ static int rv3028_probe(struct i2c_clien
+       if (ret)
+               return ret;
++      backup_bits = 0;
++      backup_mask = 0;
++
+       /* setup backup switchover mode */
+-      if (!device_property_read_u8(&client->dev, "backup-switchover-mode",
+-                                   &bsm))  {
++      dev_dbg(&client->dev, "Checking RTC backup switchover-mode\n");
++      if (!device_property_read_u32(&client->dev,
++                                    "backup-switchover-mode",
++                                    &bsm)) {
+               if (bsm <= 3) {
+-                      ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
+-                              RV3028_BACKUP_BSM_MASK,
+-                              (bsm & 0x03) << 2);
+-
+-                      if (ret)
+-                              return ret;
++                      backup_bits |= (u8)(bsm << 2);
++                      backup_mask |= RV3028_BACKUP_BSM_MASK;
+               } else {
+                       dev_warn(&client->dev, "invalid backup switchover mode value\n");
+               }
+@@ -698,15 +701,38 @@ static int rv3028_probe(struct i2c_clien
+                               break;
+               if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
+-                      ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
+-                                               RV3028_BACKUP_TCE |
+-                                               RV3028_BACKUP_TCR_MASK,
+-                                               RV3028_BACKUP_TCE | i);
+-                      if (ret)
+-                              return ret;
++                      backup_bits |= RV3028_BACKUP_TCE | i;
++                      backup_mask |= RV3028_BACKUP_TCE |
++                              RV3028_BACKUP_TCR_MASK;
+               } else {
+-                      dev_warn(&client->dev, "invalid trickle resistor value\n");
++                      dev_warn(&client->dev,
++                               "invalid trickle resistor value\n");
++              }
++      }
++
++      if (backup_mask) {
++              ret = rv3028_eeprom_read((void *)(rv3028->regmap),
++                                       RV3028_BACKUP,
++                                       (void *)&backup, 1);
++              if (!ret) {
++                      /* Write EEPROM only if needed */
++                      if ((backup & backup_mask) != backup_bits) {
++                              backup = (backup & ~backup_mask) | backup_bits;
++                              dev_dbg(&client->dev,
++                                      "Backup register doesn't match: EEPROM write required\n");
++                              ret = rv3028_eeprom_write(
++                                      (void *)(rv3028->regmap),
++                                      RV3028_BACKUP, (void *)&backup, 1);
++                      }
+               }
++
++              /* In the event of an EEPROM failure, update the register
++                 instead. */
++              if (ret)
++                      ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
++                                               backup_mask, backup_bits);
++              if (ret)
++                      return ret;
+       }
+       ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0945-rtc-rv3028-Refresh-RAM-on-EEPROM-write.patch b/target/linux/bcm27xx/patches-5.4/950-0945-rtc-rv3028-Refresh-RAM-on-EEPROM-write.patch
new file mode 100644 (file)
index 0000000..94e3038
--- /dev/null
@@ -0,0 +1,92 @@
+From 010b506d6b215673f188ed5cdc4e35419e3ea715 Mon Sep 17 00:00:00 2001
+From: Einar Vading <einar.vading@rhimagnesita.com>
+Date: Fri, 14 Aug 2020 22:14:41 +0200
+Subject: [PATCH] rtc: rv3028: Refresh RAM on EEPROM write
+
+The active RV3028 settings are in RAM so after modifying the settings in
+EEPROM the RAM should be refreshed so that they take effect.
+
+Signed-off-by: Einar Vading <einar.vading@rhimagnesita.com>
+---
+ drivers/rtc/rtc-rv3028.c | 56 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+--- a/drivers/rtc/rtc-rv3028.c
++++ b/drivers/rtc/rtc-rv3028.c
+@@ -66,6 +66,7 @@
+ #define RV3028_EVT_CTRL_TSR           BIT(2)
++#define RV3028_EEPROM_CMD_REFRESH     0x12
+ #define RV3028_EEPROM_CMD_WRITE               0x21
+ #define RV3028_EEPROM_CMD_READ                0x22
+@@ -583,6 +584,58 @@ restore_eerd:
+       return ret;
+ }
++static int rv3028_ram_refresh(void *priv)
++{
++      u32 status, ctrl1;
++      int ret, err;
++
++      ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
++      if (ret)
++              return ret;
++
++      if (!(ctrl1 & RV3028_CTRL1_EERD)) {
++              ret = regmap_update_bits(priv, RV3028_CTRL1,
++                                       RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
++              if (ret)
++                      return ret;
++
++              ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
++                                             !(status & RV3028_STATUS_EEBUSY),
++                                             RV3028_EEBUSY_POLL,
++                                             RV3028_EEBUSY_TIMEOUT);
++              if (ret)
++                      goto restore_eerd;
++      }
++
++      ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
++      if (ret)
++              goto restore_eerd;
++
++      ret = regmap_write(priv, RV3028_EEPROM_CMD,
++                         RV3028_EEPROM_CMD_REFRESH);
++      if (ret)
++              goto restore_eerd;
++
++      usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
++
++      ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
++                                     !(status & RV3028_STATUS_EEBUSY),
++                                     RV3028_EEBUSY_POLL,
++                                     RV3028_EEBUSY_TIMEOUT);
++      if (ret)
++              goto restore_eerd;
++
++restore_eerd:
++      if (!(ctrl1 & RV3028_CTRL1_EERD)) {
++              err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
++                                       0);
++              if (err && !ret)
++                      ret = err;
++      }
++
++      return ret;
++}
++
+ static struct rtc_class_ops rv3028_rtc_ops = {
+       .read_time = rv3028_get_time,
+       .set_time = rv3028_set_time,
+@@ -723,6 +776,9 @@ static int rv3028_probe(struct i2c_clien
+                               ret = rv3028_eeprom_write(
+                                       (void *)(rv3028->regmap),
+                                       RV3028_BACKUP, (void *)&backup, 1);
++
++                              if (!ret)
++                                      ret = rv3028_ram_refresh((void *)(rv3028->regmap));
+                       }
+               }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0946-dt-overlays-Add-PiFace-Digital-Device-Tree-Overlay.patch b/target/linux/bcm27xx/patches-5.4/950-0946-dt-overlays-Add-PiFace-Digital-Device-Tree-Overlay.patch
new file mode 100644 (file)
index 0000000..d9a6675
--- /dev/null
@@ -0,0 +1,199 @@
+From 296cff78df285c99a52760cbcd896abc37820e06 Mon Sep 17 00:00:00 2001
+From: Thomas Preston <thomas.preston@codethink.co.uk>
+Date: Thu, 13 Aug 2020 01:38:35 +0100
+Subject: [PATCH] dt/overlays: Add PiFace Digital Device Tree Overlay
+
+The PiFace Digital is a convenient breakout board for the Microchip
+mcp23s17 SPI GPIO port expander.
+
+The first eight GPIOs 0..7 (bank A) are connected to eight output
+terminals and LEDs, plus two relays on the first two outputs. These
+output loads are active-high.
+
+The next eight GPIOs 8..15 (bank B) are connected to eight input
+terminals with four on-board switches connecting them to ground. Inputs
+devices are therefore expected to bridge terminals to ground, so the
+mcp23s17 pullups are activated for GPIO bank B.
+
+Signed-off-by: Thomas Preston <thomas.preston@codethink.co.uk>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   8 +
+ .../dts/overlays/pifacedigital-overlay.dts    | 144 ++++++++++++++++++
+ 3 files changed, 153 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/pifacedigital-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -121,6 +121,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       papirus.dtbo \
+       pca953x.dtbo \
+       pibell.dtbo \
++      pifacedigital.dtbo \
+       piglow.dtbo \
+       piscreen.dtbo \
+       piscreen2r.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1949,6 +1949,14 @@ Params: alsaname                Set the
+                                 "PiBell")
++Name:   pifacedigital
++Info:   Configures the PiFace Digital mcp23s17 GPIO port expander.
++Load:   dtoverlay=pifacedigital,<param>=<val>
++Params: spi-present-mask        8-bit integer, bitmap indicating MCP23S17 SPI0
++                                CS0 address. PiFace Digital supports addresses
++                                0-3, which can be configured with JP1 and JP2.
++
++
+ Name:   piglow
+ Info:   Configures the PiGlow by pimoroni.com
+ Load:   dtoverlay=piglow
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/pifacedigital-overlay.dts
+@@ -0,0 +1,144 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * PiFace Digital, Device Tree Overlay.
++ * Copyright (C) 2020 Thomas Preston <thomas.preston@codethink.co.uk>
++ *
++ * The PiFace Digital is a convenient breakout board for the Microchip mcp23s17
++ * SPI GPIO port expander.
++ *
++ * The first eight GPIOs 0..7 (bank A) are connected to eight output terminals
++ * and LEDs, plus two relays on the first two outputs. These output loads are
++ * active-high.
++ *
++ * The next eight GPIOs 8..15 (bank B) are connected to eight input terminals
++ * with four on-board switches connecting them to ground. Inputs devices are
++ * therefore expected to bridge terminals to ground, so the mcp23s17 pullups are
++ * activated for GPIO bank B.
++ *
++ * On PiFace Digital, the mcp23s17 is connected to the Raspberry Pi's SPI0 CS0
++ * bus. Each SPI bus supports up to eight addressable child devices. The PiFace
++ * Digital only supports addresses 0-4, which can be configured by jumpers JP1
++ * and JP2.
++ *
++ * You can tell the driver about these jumper configurations with the
++ * spi-present-mask bitmask:
++ *
++ *     | JP1 | JP2 | dtoverlay line in /boot/config.txt         |
++ *     | --- | --- | ------------------------------------------ |
++ *     |  0  |  0  | dtoverlay=pifacedigital                    |
++ *     |  0  |  0  | dtoverlay=pifacedigital:spi-present-mask=1 |
++ *     |  0  |  1  | dtoverlay=pifacedigital:spi-present-mask=2 |
++ *     |  1  |  0  | dtoverlay=pifacedigital:spi-present-mask=4 |
++ *     |  1  |  1  | dtoverlay=pifacedigital:spi-present-mask=8 |
++ *
++ * # Example
++ * Set the dtoverlay config in /boot/config.txt and power off the Raspberry Pi:
++ *
++ *     $ grep pifacedigital /boot/config.txt
++ *     dtoverlay=pifacedigital
++ *     $ sudo systemctl poweroff
++ *
++ * Attach the PiFace Digital and power on the Raspberry Pi.
++ * Then use the libgpiod tools to query the device:
++ *
++ *     $ sudo apt install gpiod
++ *     $ gpiodetect | grep mcp23s17
++ *     gpiochip2 [mcp23s17.0] (16 lines)
++ *
++ * Set GPIO outputs 0, 2 and 5:
++ *
++ *     $ gpioset gpiochip2 0=1 2=1 5=1
++ *
++ * Get GPIO status (input GPIO 8..15 are high, because they are active-low):
++ *
++ *     $ gpioget gpiochip2 {8..15}
++ *     1 1 1 1 1 1 1 1
++ *
++ * And even monitor interrupts:
++ *
++ *     $ gpiomon gpiochip2 {8..15}
++ *     event: FALLING EDGE offset: 11 timestamp: [1597361662.926741667]
++ *     event:  RISING EDGE offset: 11 timestamp: [1597361663.062555051]
++ *
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      /* Disable exposing /dev/spidev0.0 */
++      fragment@0 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      /* Add the PiFace Digital device node to the spi0.0 device. */
++      fragment@1 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pfdigital: pifacedigital@0 {
++                              compatible = "microchip,mcp23s17";
++                              reg = <0>;
++
++                              /* Set devices present with 8-bit mask. */
++                              microchip,spi-present-mask = <0x01>;
++                              spi-max-frequency = <500000>;
++
++                              gpio-controller;
++                              #gpio-cells = <2>;
++
++                              /* This device can pass through interrupts. */
++                              interrupt-controller;
++                              #interrupt-cells = <2>;
++
++                              /* INTB is connected to GPIO 25.
++                               * 0x8 active-low level-sensitive
++                               */
++                              interrupts = <25 0x8>;
++                              interrupt-parent = <&gpio>;
++
++                              /* Configure pull-ups on bank B GPIOs */
++                              pinctrl-0 = <&pfdigital_irq &pfdigital_pullups>;
++                              pinctrl-names = "default";
++                              pfdigital_pullups: pinmux {
++                                      pins =
++                                              "gpio8",
++                                              "gpio9",
++                                              "gpio10",
++                                              "gpio11",
++                                              "gpio12",
++                                              "gpio13",
++                                              "gpio14",
++                                              "gpio15";
++                                      bias-pull-up;
++                              };
++                      };
++              };
++      };
++
++      /* PiFace Digital mcp23s17 INTB pin is connected to GPIO 25. The INTB
++       * pin is configured active-low (0 on interrupt), so expect to see
++       * FALLING_EDGE when inputs are bridged to ground (switch is pressed).
++       */
++      fragment@3 {
++              target = <&gpio>;
++              __overlay__ {
++                      pfdigital_irq: pifacedigital_irq {
++                              brcm,pins = <25>;
++                              brcm,function = <0>; /* input */
++                      };
++              };
++      };
++
++      __overrides__ {
++              spi-present-mask = <&pfdigital>, "microchip,spi-present-mask:0";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0947-overlays-Updated-MCP3008-compatible-strings.patch b/target/linux/bcm27xx/patches-5.4/950-0947-overlays-Updated-MCP3008-compatible-strings.patch
new file mode 100644 (file)
index 0000000..739c4da
--- /dev/null
@@ -0,0 +1,84 @@
+From 9c5770dd049b3839296ac49fb40f01b6fe55fa81 Mon Sep 17 00:00:00 2001
+From: RICCIARDI-Adrien <adrien.ricciardi@hotmail.fr>
+Date: Thu, 20 Aug 2020 10:18:35 +0200
+Subject: [PATCH] overlays: Updated MCP3008 compatible strings.
+
+Used recommended ones from Documentation/devicetree/bindings/iio/adc/mcp320x.txt.
+---
+ arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts
+@@ -72,7 +72,7 @@
+                       #size-cells = <0>;
+                       mcp3008_00: mcp3008@0 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <0>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -87,7 +87,7 @@
+                       #size-cells = <0>;
+                       mcp3008_01: mcp3008@1 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <1>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -102,7 +102,7 @@
+                       #size-cells = <0>;
+                       mcp3008_10: mcp3008@0 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <0>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -117,7 +117,7 @@
+                       #size-cells = <0>;
+                       mcp3008_11: mcp3008@1 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <1>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -132,7 +132,7 @@
+                       #size-cells = <0>;
+                       mcp3008_12: mcp3008@2 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <2>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -147,7 +147,7 @@
+                       #size-cells = <0>;
+                       mcp3008_20: mcp3008@0 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <0>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -162,7 +162,7 @@
+                       #size-cells = <0>;
+                       mcp3008_21: mcp3008@1 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <1>;
+                               spi-max-frequency = <1600000>;
+                       };
+@@ -177,7 +177,7 @@
+                       #size-cells = <0>;
+                       mcp3008_22: mcp3008@2 {
+-                              compatible = "mcp3008";
++                              compatible = "microchip,mcp3008";
+                               reg = <2>;
+                               spi-max-frequency = <1600000>;
+                       };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0948-RESET_CONTROLLER-needs-to-be-activated-to-compile-Br.patch b/target/linux/bcm27xx/patches-5.4/950-0948-RESET_CONTROLLER-needs-to-be-activated-to-compile-Br.patch
new file mode 100644 (file)
index 0000000..68627aa
--- /dev/null
@@ -0,0 +1,20 @@
+From b28871fe542f7805751e804ee385a803af00efae Mon Sep 17 00:00:00 2001
+From: Ramin Moussavi <lordrasmus@gmail.com>
+Date: Sat, 25 Jul 2020 22:31:49 +0200
+Subject: [PATCH] RESET_CONTROLLER needs to be activated to compile
+ Broadcom BCM2835 clock support
+
+---
+ drivers/clk/bcm/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/clk/bcm/Kconfig
++++ b/drivers/clk/bcm/Kconfig
+@@ -5,6 +5,7 @@ config CLK_BCM2835
+       depends on COMMON_CLK
+       default ARCH_BCM2835 || ARCH_BRCMSTB
+       select RESET_SIMPLE
++      select RESET_CONTROLLER
+       help
+         Enable common clock framework support for Broadcom BCM2835
+         SoCs.
diff --git a/target/linux/bcm27xx/patches-5.4/950-0949-media-dvbsky-use-a-single-mutex-and-state-buffers-fo.patch b/target/linux/bcm27xx/patches-5.4/950-0949-media-dvbsky-use-a-single-mutex-and-state-buffers-fo.patch
new file mode 100644 (file)
index 0000000..836364e
--- /dev/null
@@ -0,0 +1,64 @@
+From 08ccbb8e0667e90e5c7334057965c6205a3855fb Mon Sep 17 00:00:00 2001
+From: Andrei Koshkosh <andreykosh000@mail.ru>
+Date: Sun, 29 Sep 2019 05:04:05 -0300
+Subject: [PATCH] media: dvbsky: use a single mutex and state buffers
+ for all R/W ops
+
+commit cecf0bbbcb6f035a5ca2197f3e11ec2b7fb3da83 upstream.
+
+Re-use usb_mutex from dvb_usb_device for this.
+
+See: https://github.com/raspberrypi/linux/issues/3809
+
+Tested-by: Jan Pieter van Woerkom <jp@jpvw.nl>
+Signed-off-by: Andrei Koshkosh <andreykosh000@mail.ru>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/dvbsky.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
+@@ -22,7 +22,6 @@ MODULE_PARM_DESC(disable_rc, "Disable in
+ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+ struct dvbsky_state {
+-      struct mutex stream_mutex;
+       u8 ibuf[DVBSKY_BUF_LEN];
+       u8 obuf[DVBSKY_BUF_LEN];
+       u8 last_lock;
+@@ -60,17 +59,19 @@ static int dvbsky_usb_generic_rw(struct
+ static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
+ {
+       struct dvbsky_state *state = d_to_priv(d);
++      static const u8 obuf_pre[3] = { 0x37, 0, 0 };
++      static const u8 obuf_post[3] = { 0x36, 3, 0 };
+       int ret;
+-      u8 obuf_pre[3] = { 0x37, 0, 0 };
+-      u8 obuf_post[3] = { 0x36, 3, 0 };
+-      mutex_lock(&state->stream_mutex);
+-      ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0);
++      mutex_lock(&d->usb_mutex);
++      memcpy(state->obuf, obuf_pre, 3);
++      ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3);
+       if (!ret && onoff) {
+               msleep(20);
+-              ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0);
++              memcpy(state->obuf, obuf_post, 3);
++              ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3);
+       }
+-      mutex_unlock(&state->stream_mutex);
++      mutex_unlock(&d->usb_mutex);
+       return ret;
+ }
+@@ -598,7 +599,6 @@ static int dvbsky_init(struct dvb_usb_de
+       if (ret)
+               return ret;
+       */
+-      mutex_init(&state->stream_mutex);
+       state->last_lock = 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0950-ARM-dts-bcm2711-Enable-support-for-DDR52-eMMC.patch b/target/linux/bcm27xx/patches-5.4/950-0950-ARM-dts-bcm2711-Enable-support-for-DDR52-eMMC.patch
new file mode 100644 (file)
index 0000000..7a0e78d
--- /dev/null
@@ -0,0 +1,22 @@
+From e31ec540cff5498f86f57cccb7a35b323bdb6f33 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 24 Aug 2020 17:11:34 +0100
+Subject: [PATCH] ARM: dts: bcm2711: Enable support for DDR52 eMMC
+
+See: https://github.com/raspberrypi/linux/issues/3802
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -310,3 +310,7 @@
+ &hvs {
+       clocks = <&firmware_clocks 4>;
+ };
++
++&emmc2 {
++      mmc-ddr-3_3v;
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0951-staging-vc04_services-ISP-Fix-dmabuf-error-check-in-.patch b/target/linux/bcm27xx/patches-5.4/950-0951-staging-vc04_services-ISP-Fix-dmabuf-error-check-in-.patch
new file mode 100644 (file)
index 0000000..32f66fb
--- /dev/null
@@ -0,0 +1,25 @@
+From 971ec8a5c6229dc45b89105196a86333635fc553 Mon Sep 17 00:00:00 2001
+From: Paul Elder <paul.elder@ideasonboard.com>
+Date: Mon, 24 Aug 2020 17:14:29 +0900
+Subject: [PATCH] staging: vc04_services: ISP: Fix dmabuf error check
+ in S_CTRL
+
+In bcm2835_isp_s_ctrl, the error check for dma_buf_get() is incorrect,
+and considers ERR_PTR pointers as valid dmabufs. Fix this error check.
+
+Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
+---
+ drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -733,7 +733,7 @@ static int bcm2835_isp_s_ctrl(struct v4l
+                      sizeof(struct bcm2835_isp_lens_shading));
+               dmabuf = dma_buf_get(ls.dmabuf);
+-              if (!dmabuf)
++              if (IS_ERR_OR_NULL(dmabuf))
+                       return -EINVAL;
+               ret = vc_sm_cma_import_dmabuf(dmabuf,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0952-ARM-dts-bcm2708.dtsi-Don-t-delete-the-cpus-node.patch b/target/linux/bcm27xx/patches-5.4/950-0952-ARM-dts-bcm2708.dtsi-Don-t-delete-the-cpus-node.patch
new file mode 100644 (file)
index 0000000..2ad707d
--- /dev/null
@@ -0,0 +1,26 @@
+From a32c73cc5a06b0bf7f2b18314b46a052ce6517ee Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 24 Aug 2020 18:28:52 +0100
+Subject: [PATCH] ARM: dts: bcm2708.dtsi: Don't delete the cpus node
+
+The cpus node was originally deleted to match the then downstream
+version of the BCM2835 DTS files, but doing so doesn't seem to make
+any material difference. Its presence is necessary for the CPUFREQ_DT
+support that is planned in the near future, so remove the deletion.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2708.dtsi | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708.dtsi
++++ b/arch/arm/boot/dts/bcm2708.dtsi
+@@ -2,8 +2,6 @@
+ #include "bcm270x.dtsi"
+ / {
+-      /delete-node/ cpus;
+-
+       __overrides__ {
+               arm_freq;
+       };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0953-ARM-dts-bcm2835-Use-the-L2-non-allocating-alias.patch b/target/linux/bcm27xx/patches-5.4/950-0953-ARM-dts-bcm2835-Use-the-L2-non-allocating-alias.patch
new file mode 100644 (file)
index 0000000..d87ffc8
--- /dev/null
@@ -0,0 +1,30 @@
+From 121fdf16a2ff4cf651c376a37eeca255544c47fd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 27 Aug 2020 17:57:18 +0100
+Subject: [PATCH] ARM: dts: bcm2835: Use the L2 non-allocating alias
+
+The /soc/dma-ranges property on BCM2835 currently results in DMA
+addresses in the range 0x40000000-0x5fffffff. This will allocate in the
+system L2 cache, which may adversely affect performance.
+
+Change the dma-ranges property to give addresses in the range
+0x80000000-0x9fffffff, which are coherent with L2 but non-allocating.
+
+See: https://github.com/raspberrypi/linux/issues/3602
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2835.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/bcm2835.dtsi
++++ b/arch/arm/boot/dts/bcm2835.dtsi
+@@ -18,7 +18,7 @@
+       soc {
+               ranges = <0x7e000000 0x20000000 0x02000000>;
+-              dma-ranges = <0x40000000 0x00000000 0x20000000>;
++              dma-ranges = <0x80000000 0x00000000 0x20000000>;
+       };
+       arm-pmu {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0954-media-bcm2835-unicam-Drop-WARN-on-uing-direct-cache-.patch b/target/linux/bcm27xx/patches-5.4/950-0954-media-bcm2835-unicam-Drop-WARN-on-uing-direct-cache-.patch
new file mode 100644 (file)
index 0000000..481c55b
--- /dev/null
@@ -0,0 +1,34 @@
+From d535074e3e2c08ba5a6b627e54f4597f0f6f9240 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 27 Aug 2020 16:30:26 +0100
+Subject: [PATCH] media: bcm2835-unicam: Drop WARN on uing direct
+ cache alias
+
+Pi 0&1 pass all ARM accesses through the VPU L2 cache, therefore
+the dma-ranges property sets the cache alias bits to other
+than the direct alias, hence this WARN was firing.
+
+It was overprotective coding, so assume that everything is OK
+with the dma-ranges, and remove the WARN.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -708,13 +708,6 @@ static void unicam_wr_dma_addr(struct un
+ {
+       dma_addr_t endaddr = dmaaddr + buffer_size;
+-      /*
+-       * dmaaddr and endaddr should be a 32-bit address with the top two bits
+-       * set to 0x3 to signify uncached access through the Videocore memory
+-       * controller.
+-       */
+-      WARN_ON((dmaaddr >> 30) != 0x3 || (endaddr >> 30) != 0x3);
+-
+       if (pad_id == IMAGE_PAD) {
+               reg_write(dev, UNICAM_IBSA0, dmaaddr);
+               reg_write(dev, UNICAM_IBEA0, endaddr);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0955-media-i2c-tc358743-Only-allow-supported-pixel-fmts-i.patch b/target/linux/bcm27xx/patches-5.4/950-0955-media-i2c-tc358743-Only-allow-supported-pixel-fmts-i.patch
new file mode 100644 (file)
index 0000000..e783660
--- /dev/null
@@ -0,0 +1,30 @@
+From b443f3889a2f689c7f480211e12f17ddc3b483f8 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 10 Jul 2020 12:40:50 +0100
+Subject: [PATCH] media: i2c: tc358743: Only allow supported pixel
+ fmts in set_fmt
+
+Fix commit "media: tc358743: Return an appropriate colorspace from
+tc358743_set_fmt" to ensure that the format passed in to set_fmt
+is checked to be valid, and reset to the current format if not.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/tc358743.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/i2c/tc358743.c
++++ b/drivers/media/i2c/tc358743.c
+@@ -1731,8 +1731,10 @@ static int tc358743_set_fmt(struct v4l2_
+       u32 code = format->format.code; /* is overwritten by get_fmt */
+       int ret = tc358743_get_fmt(sd, cfg, format);
+-      format->format.code = code;
+-      format->format.colorspace = tc358743_g_colorspace(code);
++      if (code == MEDIA_BUS_FMT_RGB888_1X24 ||
++          code == MEDIA_BUS_FMT_UYVY8_1X16)
++              format->format.code = code;
++      format->format.colorspace = tc358743_g_colorspace(format->format.code);
+       if (ret)
+               return ret;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0956-media-i2c-ov9281-Add-support-for-8-bit-readout.patch b/target/linux/bcm27xx/patches-5.4/950-0956-media-i2c-ov9281-Add-support-for-8-bit-readout.patch
new file mode 100644 (file)
index 0000000..f6880c9
--- /dev/null
@@ -0,0 +1,188 @@
+From c673ce1338b69c5c8c6572e361be02356af93a72 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Tue, 7 Jul 2020 18:29:10 +0100
+Subject: [PATCH] media: i2c: ov9281: Add support for 8 bit readout
+
+The sensor supports 8 bit mode as well as 10bit, so add the
+relevant code to allow selection of this.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/ov9281.c | 66 ++++++++++++++++++++++++++++++--------
+ 1 file changed, 52 insertions(+), 14 deletions(-)
+
+--- a/drivers/media/i2c/ov9281.c
++++ b/drivers/media/i2c/ov9281.c
+@@ -29,11 +29,12 @@
+ #define OV9281_LINK_FREQ_400MHZ               400000000
+ #define OV9281_LANES                  2
+-#define OV9281_BITS_PER_SAMPLE                10
+ /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
+-#define OV9281_PIXEL_RATE             (OV9281_LINK_FREQ_400MHZ * 2 * \
+-                                       OV9281_LANES / OV9281_BITS_PER_SAMPLE)
++#define OV9281_PIXEL_RATE_10BIT               (OV9281_LINK_FREQ_400MHZ * 2 * \
++                                       OV9281_LANES / 10)
++#define OV9281_PIXEL_RATE_8BIT                (OV9281_LINK_FREQ_400MHZ * 2 * \
++                                       OV9281_LANES / 8)
+ #define OV9281_XVCLK_FREQ             24000000
+ #define CHIP_ID                               0x9281
+@@ -122,24 +123,25 @@ struct ov9281 {
+       struct v4l2_ctrl        *digi_gain;
+       struct v4l2_ctrl        *hblank;
+       struct v4l2_ctrl        *vblank;
++      struct v4l2_ctrl        *pixel_rate;
+       struct v4l2_ctrl        *test_pattern;
+       struct mutex            mutex;
+       bool                    streaming;
+       bool                    power_on;
+       const struct ov9281_mode *cur_mode;
++      u32                     code;
+ };
+ #define to_ov9281(sd) container_of(sd, struct ov9281, subdev)
+ /*
+  * Xclk 24Mhz
+- * max_framerate 120fps
++ * max_framerate 120fps for 10 bit, 144fps for 8 bit.
+  * mipi_datarate per lane 800Mbps
+  */
+ static const struct regval ov9281_1280x800_regs[] = {
+       {0x0103, 0x01},
+       {0x0302, 0x32},
+-      {0x030d, 0x50},
+       {0x030e, 0x02},
+       {0x3001, 0x00},
+       {0x3004, 0x00},
+@@ -168,7 +170,6 @@ static const struct regval ov9281_1280x8
+       {0x3620, 0x6f},
+       {0x3632, 0x56},
+       {0x3633, 0x78},
+-      {0x3662, 0x05},
+       {0x3666, 0x00},
+       {0x366f, 0x5a},
+       {0x3680, 0x84},
+@@ -235,6 +236,18 @@ static const struct regval ov9281_1280x8
+       {REG_NULL, 0x00},
+ };
++static const struct regval op_10bit[] = {
++      {0x030d, 0x50},
++      {0x3662, 0x05},
++      {REG_NULL, 0x00},
++};
++
++static const struct regval op_8bit[] = {
++      {0x030d, 0x60},
++      {0x3662, 0x07},
++      {REG_NULL, 0x00},
++};
++
+ static const struct ov9281_mode supported_modes[] = {
+       {
+               .width = 1280,
+@@ -374,12 +387,13 @@ static int ov9281_set_fmt(struct v4l2_su
+ {
+       struct ov9281 *ov9281 = to_ov9281(sd);
+       const struct ov9281_mode *mode;
+-      s64 h_blank, vblank_def;
++      s64 h_blank, vblank_def, pixel_rate;
+       mutex_lock(&ov9281->mutex);
+       mode = ov9281_find_best_fit(fmt);
+-      fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
++      if (fmt->format.code != MEDIA_BUS_FMT_Y8_1X8)
++              fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
+       fmt->format.width = mode->width;
+       fmt->format.height = mode->height;
+       fmt->format.field = V4L2_FIELD_NONE;
+@@ -396,6 +410,7 @@ static int ov9281_set_fmt(struct v4l2_su
+               *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
+       } else {
+               ov9281->cur_mode = mode;
++              ov9281->code = fmt->format.code;
+               h_blank = mode->hts_def - mode->width;
+               __v4l2_ctrl_modify_range(ov9281->hblank, h_blank,
+                                        h_blank, 1, h_blank);
+@@ -405,6 +420,11 @@ static int ov9281_set_fmt(struct v4l2_su
+                                        OV9281_VTS_MAX - mode->height,
+                                        1, vblank_def);
+               __v4l2_ctrl_s_ctrl(ov9281->vblank, vblank_def);
++
++              pixel_rate = (fmt->format.code == MEDIA_BUS_FMT_Y10_1X10) ?
++                      OV9281_PIXEL_RATE_10BIT : OV9281_PIXEL_RATE_8BIT;
++              __v4l2_ctrl_modify_range(ov9281->pixel_rate, pixel_rate,
++                                       pixel_rate, 1, pixel_rate);
+       }
+       mutex_unlock(&ov9281->mutex);
+@@ -425,7 +445,7 @@ static int ov9281_get_fmt(struct v4l2_su
+       } else {
+               fmt->format.width = mode->width;
+               fmt->format.height = mode->height;
+-              fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
++              fmt->format.code = ov9281->code;
+               fmt->format.field = V4L2_FIELD_NONE;
+               fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
+               fmt->format.ycbcr_enc =
+@@ -446,9 +466,16 @@ static int ov9281_enum_mbus_code(struct
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_mbus_code_enum *code)
+ {
+-      if (code->index)
++      switch (code->index) {
++      default:
+               return -EINVAL;
+-      code->code = MEDIA_BUS_FMT_Y10_1X10;
++      case 0:
++              code->code = MEDIA_BUS_FMT_Y10_1X10;
++              break;
++      case 1:
++              code->code = MEDIA_BUS_FMT_Y8_1X8;
++              break;
++      }
+       return 0;
+ }
+@@ -460,7 +487,8 @@ static int ov9281_enum_frame_sizes(struc
+       if (fse->index >= ARRAY_SIZE(supported_modes))
+               return -EINVAL;
+-      if (fse->code != MEDIA_BUS_FMT_Y10_1X10)
++      if (fse->code != MEDIA_BUS_FMT_Y10_1X10 &&
++          fse->code != MEDIA_BUS_FMT_Y8_1X8)
+               return -EINVAL;
+       fse->min_width  = supported_modes[fse->index].width;
+@@ -543,6 +571,13 @@ static int __ov9281_start_stream(struct
+       if (ret)
+               return ret;
++      if (ov9281->code == MEDIA_BUS_FMT_Y10_1X10)
++              ret = ov9281_write_array(ov9281->client, op_10bit);
++      else
++              ret = ov9281_write_array(ov9281->client, op_8bit);
++      if (ret)
++              return ret;
++
+       /* In case these controls are set before streaming */
+       mutex_unlock(&ov9281->mutex);
+       ret = v4l2_ctrl_handler_setup(&ov9281->ctrl_handler);
+@@ -849,8 +884,11 @@ static int ov9281_initialize_controls(st
+       if (ctrl)
+               ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+-      v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
+-                        0, OV9281_PIXEL_RATE, 1, OV9281_PIXEL_RATE);
++      ov9281->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
++                                             V4L2_CID_PIXEL_RATE,
++                                             OV9281_PIXEL_RATE_10BIT,
++                                             OV9281_PIXEL_RATE_10BIT, 1,
++                                             OV9281_PIXEL_RATE_10BIT);
+       h_blank = mode->hts_def - mode->width;
+       ov9281->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0957-overlays-Add-spi0-1cs-and-spi0-2cs.patch b/target/linux/bcm27xx/patches-5.4/950-0957-overlays-Add-spi0-1cs-and-spi0-2cs.patch
new file mode 100644 (file)
index 0000000..3af45bb
--- /dev/null
@@ -0,0 +1,199 @@
+From 692af7a59fd6d9d3b64edbf028cd75b0096ef8c7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 28 Aug 2020 12:55:41 +0100
+Subject: [PATCH] overlays: Add spi0-1cs and spi0-2cs
+
+The spi0-1cs overlay allows the SPI0 interface to be run with a single
+CS line, which can be useful if GPIOs are in short supply. The no_miso
+parameter is for write-only devices that don't need the return channel,
+and again is there to free up a GPIO.
+
+spi0-2cs is the new name for spi0-cs (now deprecated with a redirect
+to spi0-2cs), but with the addedd no_miso parameter.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  3 +-
+ arch/arm/boot/dts/overlays/README             | 22 ++++++++--
+ arch/arm/boot/dts/overlays/overlay_map.dts    |  4 ++
+ .../boot/dts/overlays/spi0-1cs-overlay.dts    | 42 +++++++++++++++++++
+ ...i0-cs-overlay.dts => spi0-2cs-overlay.dts} |  8 ++++
+ 5 files changed, 75 insertions(+), 4 deletions(-)
+ create mode 100644 arch/arm/boot/dts/overlays/spi0-1cs-overlay.dts
+ rename arch/arm/boot/dts/overlays/{spi0-cs-overlay.dts => spi0-2cs-overlay.dts} (79%)
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -161,7 +161,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       spi-gpio35-39.dtbo \
+       spi-gpio40-45.dtbo \
+       spi-rtc.dtbo \
+-      spi0-cs.dtbo \
++      spi0-1cs.dtbo \
++      spi0-2cs.dtbo \
+       spi1-1cs.dtbo \
+       spi1-2cs.dtbo \
+       spi1-3cs.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2412,11 +2412,27 @@ Load:   dtoverlay=spi-rtc,<param>=<val>
+ Params: pcf2123                 Select the PCF2123 device
+-Name:   spi0-cs
+-Info:   Allows the (software) CS pins for SPI0 to be changed
+-Load:   dtoverlay=spi0-cs,<param>=<val>
++Name:   spi0-1cs
++Info:   Only use one CS pin for SPI0
++Load:   dtoverlay=spi0-1cs,<param>=<val>
++Params: cs0_pin                 GPIO pin for CS0 (default 8)
++        no_miso                 Don't claim and use the MISO pin (9), freeing
++                                it for other uses.
++
++
++Name:   spi0-2cs
++Info:   Change the CS pins for SPI0
++Load:   dtoverlay=spi0-2cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 8)
+         cs1_pin                 GPIO pin for CS1 (default 7)
++        no_miso                 Don't claim and use the MISO pin (9), freeing
++                                it for other uses.
++
++
++Name:   spi0-cs
++Info:   This overlay has been renamed spi0-1cs, keeping spi0-cs as an
++        alias for backwards compatibility.
++Load:   <Deprecated>
+ Name:   spi0-hw-cs
+--- a/arch/arm/boot/dts/overlays/overlay_map.dts
++++ b/arch/arm/boot/dts/overlays/overlay_map.dts
+@@ -61,6 +61,10 @@
+               deprecated = "use sdio,bus_width=1,gpios_22_25";
+       };
++      spi0-cs {
++              renamed = "spi0-2cs";
++      };
++
+       spi0-hw-cs {
+               deprecated = "no longer necessary";
+       };
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi0-1cs-overlay.dts
+@@ -0,0 +1,42 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <8>;
++              };
++      };
++
++      fragment@1 {
++              target = <&spi0>;
++              frag1: __overlay__ {
++                      cs-gpios = <&gpio 8 1>;
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@3 {
++              target = <&spi0_pins>;
++              __dormant__ {
++                      brcm,pins = <10 11>;
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              no_miso = <0>,"=3";
++      };
++};
+--- a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/dts-v1/;
+-/plugin/;
+-
+-
+-/ {
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&spi0_cs_pins>;
+-              frag0: __overlay__ {
+-                      brcm,pins = <8 7>;
+-              };
+-      };
+-
+-      fragment@1 {
+-              target = <&spi0>;
+-              frag1: __overlay__ {
+-                      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
+-                      status = "okay";
+-              };
+-      };
+-
+-      __overrides__ {
+-              cs0_pin  = <&frag0>,"brcm,pins:0",
+-                         <&frag1>,"cs-gpios:4";
+-              cs1_pin  = <&frag0>,"brcm,pins:4",
+-                         <&frag1>,"cs-gpios:16";
+-      };
+-};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/spi0-2cs-overlay.dts
+@@ -0,0 +1,37 @@
++/dts-v1/;
++/plugin/;
++
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spi0_cs_pins>;
++              frag0: __overlay__ {
++                      brcm,pins = <8 7>;
++              };
++      };
++
++      fragment@1 {
++              target = <&spi0>;
++              frag1: __overlay__ {
++                      cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&spi0_pins>;
++              __dormant__ {
++                      brcm,pins = <10 11>;
++              };
++      };
++
++      __overrides__ {
++              cs0_pin  = <&frag0>,"brcm,pins:0",
++                         <&frag1>,"cs-gpios:4";
++              cs1_pin  = <&frag0>,"brcm,pins:4",
++                         <&frag1>,"cs-gpios:16";
++              no_miso = <0>,"=2";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0958-overlays-Fix-error-in-README.patch b/target/linux/bcm27xx/patches-5.4/950-0958-overlays-Fix-error-in-README.patch
new file mode 100644 (file)
index 0000000..ab6db1e
--- /dev/null
@@ -0,0 +1,23 @@
+From 9102032e6d06f271058b6bd98db453a2275ec9b9 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 28 Aug 2020 22:04:05 +0100
+Subject: [PATCH] overlays: Fix error in README
+
+spi0-cs has been renamed spi0-2cs, not spi0-1cs.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2430,7 +2430,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi0-cs
+-Info:   This overlay has been renamed spi0-1cs, keeping spi0-cs as an
++Info:   This overlay has been renamed spi0-2cs, keeping spi0-cs as an
+         alias for backwards compatibility.
+ Load:   <Deprecated>
diff --git a/target/linux/bcm27xx/patches-5.4/950-0959-overlays-Minor-README-correction.patch b/target/linux/bcm27xx/patches-5.4/950-0959-overlays-Minor-README-correction.patch
new file mode 100644 (file)
index 0000000..1cc7ff9
--- /dev/null
@@ -0,0 +1,21 @@
+From 8314b7ffe066745d9a2045e2ecaf287487342df3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 2 Sep 2020 08:39:57 +0100
+Subject: [PATCH] overlays: Minor README correction
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -134,7 +134,7 @@ Params:
+                                 6=Alt                    7=Speed/Flash
+                                 8=Link                   9=Activity
+-        eth_led1                Set mode of LED1 - green on Pi3B (default "6"),
++        eth_led1                Set mode of LED1 - green on Pi3B+ (default "6"),
+                                 amber on Pi4 (default "8"). See eth_led0 for
+                                 legal values.
diff --git a/target/linux/bcm27xx/patches-5.4/950-0960-staging-fbtft-Add-support-for-display-variants.patch b/target/linux/bcm27xx/patches-5.4/950-0960-staging-fbtft-Add-support-for-display-variants.patch
new file mode 100644 (file)
index 0000000..185e8eb
--- /dev/null
@@ -0,0 +1,204 @@
+From fe85ae40abf546bf592d171de942c17238103e52 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 1 Sep 2020 18:15:27 +0100
+Subject: [PATCH] staging/fbtft: Add support for display variants
+
+Display variants are intended as a replacement for the now-deleted
+fbtft_device drivers. Drivers can register additional compatible
+strings with a custom callback that can make the required changes
+to the fbtft_display structure.
+
+Start the ball rolling by adding adafruit18, adafruit18_green and
+sainsmart18 displays.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/staging/fbtft/fb_st7735r.c | 38 +++++++++++++++++++++++++++++-
+ drivers/staging/fbtft/fbtft-core.c | 15 +++++++++++-
+ drivers/staging/fbtft/fbtft.h      | 28 +++++++++++++++++-----
+ 3 files changed, 73 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/fbtft/fb_st7735r.c
++++ b/drivers/staging/fbtft/fb_st7735r.c
+@@ -16,6 +16,10 @@
+ #define DEFAULT_GAMMA   "0F 1A 0F 18 2F 28 20 22 1F 1B 23 37 00 07 02 10\n" \
+                       "0F 1B 0F 17 33 2C 29 2E 30 30 39 3F 00 07 03 10"
++#define ADAFRUIT18_GAMMA \
++                      "02 1c 07 12 37 32 29 2d 29 25 2B 39 00 01 03 10\n" \
++                      "03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10"
++
+ static const s16 default_init_sequence[] = {
+       -1, MIPI_DCS_SOFT_RESET,
+       -2, 150,                               /* delay */
+@@ -94,6 +98,14 @@ static void set_addr_win(struct fbtft_pa
+       write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
+ }
++static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
++                                            int xs, int ys, int xe, int ye)
++{
++      write_reg(par, 0x2A, 0, xs + 2, 0, xe + 2);
++      write_reg(par, 0x2B, 0, ys + 1, 0, ye + 1);
++      write_reg(par, 0x2C);
++}
++
+ #define MY BIT(7)
+ #define MX BIT(6)
+ #define MV BIT(5)
+@@ -174,12 +186,36 @@ static struct fbtft_display display = {
+       },
+ };
+-FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7735r", &display);
++int variant_adafruit18(struct fbtft_display *display)
++{
++      display->gamma = ADAFRUIT18_GAMMA;
++      return 0;
++}
++
++int variant_adafruit18_green(struct fbtft_display *display)
++{
++      display->gamma = ADAFRUIT18_GAMMA;
++      display->fbtftops.set_addr_win = adafruit18_green_tab_set_addr_win;
++      return 0;
++}
++
++FBTFT_REGISTER_DRIVER_START(&display)
++FBTFT_COMPATIBLE("sitronix,st7735r")
++FBTFT_COMPATIBLE("fbtft,sainsmart18")
++FBTFT_VARIANT_COMPATIBLE("fbtft,adafruit18", variant_adafruit18)
++FBTFT_VARIANT_COMPATIBLE("fbtft,adafruit18_green", variant_adafruit18_green)
++FBTFT_REGISTER_DRIVER_END(DRVNAME, &display);
+ MODULE_ALIAS("spi:" DRVNAME);
+ MODULE_ALIAS("platform:" DRVNAME);
+ MODULE_ALIAS("spi:st7735r");
+ MODULE_ALIAS("platform:st7735r");
++MODULE_ALIAS("spi:sainsmart18");
++MODULE_ALIAS("platform:sainsmart");
++MODULE_ALIAS("spi:adafruit18");
++MODULE_ALIAS("platform:adafruit18");
++MODULE_ALIAS("spi:adafruit18_green");
++MODULE_ALIAS("platform:adafruit18_green");
+ MODULE_DESCRIPTION("FB driver for the ST7735R LCD Controller");
+ MODULE_AUTHOR("Noralf Tronnes");
+--- a/drivers/staging/fbtft/fbtft-core.c
++++ b/drivers/staging/fbtft/fbtft-core.c
+@@ -24,6 +24,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/spinlock.h>
+ #include <linux/of.h>
++#include <linux/of_device.h>
+ #include <video/mipi_display.h>
+ #include "fbtft.h"
+@@ -1200,6 +1201,7 @@ static struct fbtft_platform_data *fbtft
+  * @display: Display properties
+  * @sdev: SPI device
+  * @pdev: Platform device
++ * @dt_ids: Compatible string table
+  *
+  * Allocates, initializes and registers a framebuffer
+  *
+@@ -1209,12 +1211,15 @@ static struct fbtft_platform_data *fbtft
+  */
+ int fbtft_probe_common(struct fbtft_display *display,
+                      struct spi_device *sdev,
+-                     struct platform_device *pdev)
++                     struct platform_device *pdev,
++                     const struct of_device_id *dt_ids)
+ {
+       struct device *dev;
+       struct fb_info *info;
+       struct fbtft_par *par;
+       struct fbtft_platform_data *pdata;
++      const struct of_device_id *match;
++      int (*variant)(struct fbtft_display *);
+       int ret;
+       if (sdev)
+@@ -1230,6 +1235,14 @@ int fbtft_probe_common(struct fbtft_disp
+               pdata = fbtft_probe_dt(dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
++              match = of_match_device(dt_ids, dev);
++              if (match && match->data) {
++                      /* apply the variant */
++                      variant = match->data;
++                      ret = (*variant)(display);
++                      if (ret)
++                              return ret;
++              }
+       }
+       info = fbtft_framebuffer_alloc(display, dev, pdata);
+--- a/drivers/staging/fbtft/fbtft.h
++++ b/drivers/staging/fbtft/fbtft.h
+@@ -251,7 +251,8 @@ void fbtft_register_backlight(struct fbt
+ void fbtft_unregister_backlight(struct fbtft_par *par);
+ int fbtft_init_display(struct fbtft_par *par);
+ int fbtft_probe_common(struct fbtft_display *display, struct spi_device *sdev,
+-                     struct platform_device *pdev);
++                     struct platform_device *pdev,
++                     const struct of_device_id *dt_ids);
+ int fbtft_remove_common(struct device *dev, struct fb_info *info);
+ /* fbtft-io.c */
+@@ -272,11 +273,13 @@ void fbtft_write_reg8_bus9(struct fbtft_
+ void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
+ void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
+-#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display)                \
++#define FBTFT_REGISTER_DRIVER_START(_display)                              \
++                                                                         \
++static const struct of_device_id dt_ids[];                                 \
+                                                                          \
+ static int fbtft_driver_probe_spi(struct spi_device *spi)                  \
+ {                                                                          \
+-      return fbtft_probe_common(_display, spi, NULL);                    \
++      return fbtft_probe_common(_display, spi, NULL, dt_ids);            \
+ }                                                                          \
+                                                                          \
+ static int fbtft_driver_remove_spi(struct spi_device *spi)                 \
+@@ -288,7 +291,7 @@ static int fbtft_driver_remove_spi(struc
+                                                                          \
+ static int fbtft_driver_probe_pdev(struct platform_device *pdev)           \
+ {                                                                          \
+-      return fbtft_probe_common(_display, NULL, pdev);                   \
++      return fbtft_probe_common(_display, NULL, pdev, dt_ids);           \
+ }                                                                          \
+                                                                          \
+ static int fbtft_driver_remove_pdev(struct platform_device *pdev)          \
+@@ -298,8 +301,16 @@ static int fbtft_driver_remove_pdev(stru
+       return fbtft_remove_common(&pdev->dev, info);                      \
+ }                                                                          \
+                                                                          \
+-static const struct of_device_id dt_ids[] = {                              \
+-      { .compatible = _compatible },                                     \
++static const struct of_device_id dt_ids[] = {
++
++#define FBTFT_COMPATIBLE(_compatible)                                      \
++      { .compatible = _compatible },
++
++#define FBTFT_VARIANT_COMPATIBLE(_compatible, _variant)                    \
++      { .compatible = _compatible, .data = _variant },
++
++#define FBTFT_REGISTER_DRIVER_END(_name, _display)                         \
++                                                                         \
+       {},                                                                \
+ };                                                                         \
+                                                                          \
+@@ -344,6 +355,11 @@ static void __exit fbtft_driver_module_e
+ module_init(fbtft_driver_module_init);                                     \
+ module_exit(fbtft_driver_module_exit);
++#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display)                \
++      FBTFT_REGISTER_DRIVER_START(_display)                              \
++      FBTFT_COMPATIBLE(_compatible)                                      \
++      FBTFT_REGISTER_DRIVER_END(_name, _display)
++
+ /* Debug macros */
+ /* shorthand debug levels */
diff --git a/target/linux/bcm27xx/patches-5.4/950-0961-overlays-Add-adafruit18-and-sainsmart18-overlays.patch b/target/linux/bcm27xx/patches-5.4/950-0961-overlays-Add-adafruit18-and-sainsmart18-overlays.patch
new file mode 100644 (file)
index 0000000..986ddd4
--- /dev/null
@@ -0,0 +1,169 @@
+From dde4afa87452e8499c611c9a889f4c5f35d9e2bb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 3 Sep 2020 17:36:00 +0100
+Subject: [PATCH] overlays: Add adafruit18 and sainsmart18 overlays
+
+Add support for three ST7735R-based displays - adafruit18,
+adafruit18_green and sainsmart18.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  2 +
+ arch/arm/boot/dts/overlays/README             | 15 ++++++
+ .../boot/dts/overlays/adafruit18-overlay.dts  | 49 +++++++++++++++++++
+ .../boot/dts/overlays/sainsmart18-overlay.dts | 47 ++++++++++++++++++
+ 4 files changed, 113 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/adafruit18-overlay.dts
+ create mode 100644 arch/arm/boot/dts/overlays/sainsmart18-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += overlay_ma
+ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       act-led.dtbo \
++      adafruit18.dtbo \
+       adau1977-adc.dtbo \
+       adau7002-simple.dtbo \
+       ads1015.dtbo \
+@@ -147,6 +148,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       rpi-tv.dtbo \
+       rpivid-v4l2.dtbo \
+       rra-digidac1-wm8741-audio.dtbo \
++      sainsmart18.dtbo \
+       sc16is750-i2c.dtbo \
+       sc16is752-i2c.dtbo \
+       sc16is752-spi0.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -261,6 +261,14 @@ Params: activelow               Set to "
+                                 REQUIRED
++Name:   adafruit18
++Info:   Overlay for the SPI-connected Adafruit 1.8" display (based on the
++        ST7735R chip). It includes support for the "green tab" version.
++Load:   dtoverlay=adafruit18,<param>=<val>
++Params: green                   Use the adafruit18_green variant.
++        rotate                  Display rotation {0,90,180,270}
++
++
+ Name:   adau1977-adc
+ Info:   Overlay for activation of ADAU1977 ADC codec over I2C for control
+         and I2S for data.
+@@ -2251,6 +2259,13 @@ Load:   dtoverlay=rra-digidac1-wm8741-au
+ Params: <None>
++Name:   sainsmart18
++Info:   Overlay for the SPI-connected Sainsmart 1.8" display (based on the
++        ST7735R chip).
++Load:   dtoverlay=sainsmart18,<param>=<val>
++Params: rotate                  Display rotation {0,90,180,270}
++
++
+ Name:   sc16is750-i2c
+ Info:   Overlay for the NXP SC16IS750 UART with I2C Interface
+         Enables the chip on I2C1 at 0x48 (or the "addr" parameter value). To
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/adafruit18-overlay.dts
+@@ -0,0 +1,49 @@
++/*
++ * Device Tree overlay for Adafruit 1.8" TFT LCD with ST7735R chip 160x128
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@1 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      af18: adafruit18@0 {
++                              compatible = "fbtft,adafruit18";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              spi-max-frequency = <40000000>;
++                              rotate = <90>;
++                              buswidth = <8>;
++                              fps = <50>;
++                              height = <160>;
++                              width = <128>;
++                              reset-gpios = <&gpio 25 0>;
++                              dc-gpios = <&gpio 24 0>;
++                              led-gpios = <&gpio 18 0>;
++                              bgr;
++                              debug = <0>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              green = <&af18>, "compatible=fbtft,adafruit18_green";
++              rotate = <&af18>, "rotate:0";
++      };
++};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/sainsmart18-overlay.dts
+@@ -0,0 +1,47 @@
++/*
++ * Device Tree overlay for the Sainsmart 1.8" TFT LCD with ST7735R chip 160x128
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@1 {
++              target = <&spi0>;
++              __overlay__ {
++                      /* needed to avoid dtc warning */
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      ss18: sainsmart18@0 {
++                              compatible = "fbtft,sainsmart18";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              spi-max-frequency = <40000000>;
++                              rotate = <90>;
++                              buswidth = <8>;
++                              fps = <50>;
++                              height = <160>;
++                              width = <128>;
++                              reset-gpios = <&gpio 25 0>;
++                              dc-gpios = <&gpio 24 0>;
++                              bgr;
++                              debug = <0>;
++                      };
++              };
++      };
++
++      __overrides__ {
++              rotate = <&ss18>, "rotate:0";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0962-ARM-dts-Limit-BT-modem-baud-rate-on-3B.patch b/target/linux/bcm27xx/patches-5.4/950-0962-ARM-dts-Limit-BT-modem-baud-rate-on-3B.patch
new file mode 100644 (file)
index 0000000..f88cc7b
--- /dev/null
@@ -0,0 +1,28 @@
+From 27f210c863d3349d41e366fb7573e9dcc0708e3d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 4 Sep 2020 09:04:29 +0100
+Subject: [PATCH] ARM: dts: Limit BT modem baud rate on 3B
+
+The 3B doesn't have the flow control signals connected to the BT modem,
+which limits the maximum usable baud rate to below 1 Mbaud. Use
+921600 as a relatively safe default value, but the krnbt_baudrate
+parameter can still override it.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -117,6 +117,10 @@
+       status = "okay";
+ };
++&bt {
++      max-speed = <921600>;
++};
++
+ &spi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0963-overlays-Update-i2c0-overlay-to-disable-the-i2c0mux.patch b/target/linux/bcm27xx/patches-5.4/950-0963-overlays-Update-i2c0-overlay-to-disable-the-i2c0mux.patch
new file mode 100644 (file)
index 0000000..3ce5e0b
--- /dev/null
@@ -0,0 +1,70 @@
+From 2be1e1c949138b40aac6be1e6f761c69e98dcf66 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 3 Sep 2020 14:59:40 +0100
+Subject: [PATCH] overlays: Update i2c0 overlay to disable the
+ i2c0mux.
+
+The i2c0 overlay was assigning pinctrl settings to node i2c0,
+which is now the port@0 output of the mux. That leaves a high
+chance of it colliding with the port@1 output and not doing
+what was intended.
+
+Set the i2c0 overlay to disable i2c0mux, set the pin-ctrl on
+the root i2c controller, and redirect the alias, so overall it
+behaves exactly as before.
+Combining with dtparam=i2c_vc=on is going to cause conflicts,
+so this is noted in the README.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README           |  7 +++++++
+ arch/arm/boot/dts/overlays/i2c0-overlay.dts | 15 ++++++++++++++-
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1354,6 +1354,13 @@ Name:   i2c0
+ Info:   Change i2c0 pin usage. Not all pin combinations are usable on all
+         platforms - platforms other then Compute Modules can only use this
+         to disable transaction combining.
++        Do NOT use in conjunction with dtparam=i2c_vc=on. From the 5.4 kernel
++        onwards the base DT includes the use of i2c_mux_pinctrl to expose two
++        muxings of BSC0 - GPIOs 0&1, and whichever combination is used for the
++        camera and display connectors. This overlay disables that mux and
++        configures /dev/i2c0 to point at whichever set of pins is requested.
++        dtparam=i2c_vc=on will try and enable the mux, so combining the two
++        will cause conflicts.
+ Load:   dtoverlay=i2c0,<param>=<val>
+ Params: pins_0_1                Use pins 0 and 1 (default)
+         pins_28_29              Use pins 28 and 29
+--- a/arch/arm/boot/dts/overlays/i2c0-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c0-overlay.dts
+@@ -5,7 +5,7 @@
+       compatible = "brcm,bcm2835";
+       fragment@0 {
+-              target = <&i2c0>;
++              target = <&i2c0if>;
+               __overlay__ {
+                       status = "okay";
+                       pinctrl-0 = <&i2c0_pins>;
+@@ -51,6 +51,19 @@
+               };
+       };
++      fragment@6 {
++              target = <&i2c0mux>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++
++      fragment@7 {
++              target-path = "/aliases";
++              __overlay__ {
++                      i2c0 = "/soc/i2c@7e205000";
++              };
++      };
+       __overrides__ {
+               pins_0_1   = <0>,"+1-2-3-4";
+               pins_28_29 = <0>,"-1+2-3-4";
diff --git a/target/linux/bcm27xx/patches-5.4/950-0964-dt-Remove-duplicate-assignment-for-i2c0-pinctrl-conf.patch b/target/linux/bcm27xx/patches-5.4/950-0964-dt-Remove-duplicate-assignment-for-i2c0-pinctrl-conf.patch
new file mode 100644 (file)
index 0000000..ce3d9b5
--- /dev/null
@@ -0,0 +1,155 @@
+From 12bd4eee1bb882417a38c2b5c9790e97725e489d Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 3 Sep 2020 15:12:50 +0100
+Subject: [PATCH] dt: Remove duplicate assignment for i2c0 pinctrl
+ config
+
+The include file bcm283x-rpi-i2c0mux_0_XX.dtsi was setting
+pinctrl-0 on i2c0mux, as were the individual platform DT files.
+
+Remove this duplication and rely on the include file.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2708-rpi-b-plus.dts   | 4 ----
+ arch/arm/boot/dts/bcm2708-rpi-b.dts        | 4 ----
+ arch/arm/boot/dts/bcm2708-rpi-cm.dts       | 4 ----
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts   | 4 ----
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts     | 4 ----
+ arch/arm/boot/dts/bcm2709-rpi-2-b.dts      | 4 ----
+ arch/arm/boot/dts/bcm2710-rpi-2-b.dts      | 4 ----
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 4 ----
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts      | 4 ----
+ arch/arm/boot/dts/bcm2710-rpi-cm3.dts      | 4 ----
+ 10 files changed, 40 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
+@@ -73,10 +73,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts
+@@ -73,10 +73,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts
+@@ -72,10 +72,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -122,10 +122,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -76,10 +76,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts
+@@ -73,10 +73,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2710-rpi-2-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts
+@@ -73,10 +73,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -132,10 +132,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -147,10 +147,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts
+@@ -92,10 +92,6 @@
+       clock-frequency = <100000>;
+ };
+-&i2c0mux {
+-      pinctrl-0 = <&i2c0_pins>;
+-};
+-
+ &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0965-overlays-Add-option-for-composite-to-vc4-kms-v3d-pi4.patch b/target/linux/bcm27xx/patches-5.4/950-0965-overlays-Add-option-for-composite-to-vc4-kms-v3d-pi4.patch
new file mode 100644 (file)
index 0000000..0334261
--- /dev/null
@@ -0,0 +1,68 @@
+From bbced22ee3d4c08612bbc35c860d2274e85d5a51 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 27 Aug 2020 18:57:26 +0100
+Subject: [PATCH] overlays: Add option for composite to
+ vc4-kms-v3d-pi4.
+
+Composite is an alternative to HDMI/DPI/DSI on Pi4 as it
+requires very particular clock setups.
+Add an option to vc4-kms-v3d-pi4 to enable composite and
+disable all other graphics outputs.
+
+NB This must be used in conjunction with enable_tvout=1
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README             |  2 ++
+ .../dts/overlays/vc4-kms-v3d-pi4-overlay.dts  | 26 +++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2924,6 +2924,8 @@ Params: cma-256                 CMA is 2
+         audio1                  Enable or disable audio over HDMI1 (default
+                                 "on")
+         noaudio                 Disable all HDMI audio (default "off")
++        composite               Enable the composite output (disables all other
++                                outputs)
+ Name:   vga666
+--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts
+@@ -152,9 +152,35 @@
+               };
+       };
++      fragment@21 {
++              target = <&pixelvalve3>;
++              __dormant__  {
++                      status = "okay";
++              };
++      };
++
++      fragment@22 {
++              target = <&vec>;
++              __dormant__  {
++                      status = "okay";
++              };
++      };
++
+       __overrides__ {
+               audio   = <0>,"!17";
+               audio1   = <0>,"!18";
+               noaudio = <0>,"=17", <0>,"=18", <0>,"!19";
++              composite = <0>, "!1",
++                          <0>, "!2",
++                          <0>, "!3",
++                          <0>, "!4",
++                          <0>, "!6",
++                          <0>, "!7",
++                          <0>, "!8",
++                          <0>, "!9",
++                          <0>, "!10",
++                          <0>, "!16",
++                          <0>, "=21",
++                          <0>, "=22";
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0966-minor-typo-in-directions.patch b/target/linux/bcm27xx/patches-5.4/950-0966-minor-typo-in-directions.patch
new file mode 100644 (file)
index 0000000..2a64933
--- /dev/null
@@ -0,0 +1,20 @@
+From 8f2841137865fb064ab59fc60b2bd22bbd27078a Mon Sep 17 00:00:00 2001
+From: lsellens <lsellens@gmail.com>
+Date: Mon, 14 Sep 2020 22:35:39 -0500
+Subject: [PATCH] minor typo in directions
+
+---
+ arch/arm/boot/dts/overlays/gpio-fan-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts
+@@ -31,7 +31,7 @@
+  *    - sudo nano /boot/config.txt add "dtoverlay=gpio-fan" or "dtoverlay=gpio-fan,gpiopin=12,temp=45000"
+  *     or
+  *    - sudo sh -c 'printf "\n# Enable PI GPIO-Fan Default\ndtoverlay=gpio-fan\n" >> /boot/config.txt'
+- *    - sudo sh -c 'printf "\n# Enable PI GPIO-Fan Custom\ntoverlay=gpio-fan,gpiopin=12,temp=45000\n" >> /boot/config.txt'
++ *    - sudo sh -c 'printf "\n# Enable PI GPIO-Fan Custom\ndtoverlay=gpio-fan,gpiopin=12,temp=45000\n" >> /boot/config.txt'
+  *
+  */
+ /dts-v1/;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0967-overlays-Regenerate-upstream-pi4-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-0967-overlays-Regenerate-upstream-pi4-overlay.patch
new file mode 100644 (file)
index 0000000..c025aa2
--- /dev/null
@@ -0,0 +1,31 @@
+From b1345dbdf08ded4350233bc95925647d01e936f8 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 14 Sep 2020 15:49:38 +0100
+Subject: [PATCH] overlays: Regenerate upstream-pi4 overlay
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
+@@ -134,6 +134,18 @@
+               };
+       };
+       fragment@21 {
++              target = <&pixelvalve3>;
++              __dormant__ {
++                      status = "okay";
++              };
++      };
++      fragment@22 {
++              target = <&vec>;
++              __dormant__ {
++                      status = "okay";
++              };
++      };
++      fragment@23 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0968-overlays-Add-parameters-to-adafruit18-sainsmart18.patch b/target/linux/bcm27xx/patches-5.4/950-0968-overlays-Add-parameters-to-adafruit18-sainsmart18.patch
new file mode 100644 (file)
index 0000000..99ef611
--- /dev/null
@@ -0,0 +1,94 @@
+From 9249fb1ac6b8bfcc0056fe2a871d4965b774c667 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 14 Sep 2020 15:48:16 +0100
+Subject: [PATCH] overlays: Add parameters to adafruit18, sainsmart18
+
+Also fix polarity of the reset GPIO.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README                  | 13 +++++++++++++
+ arch/arm/boot/dts/overlays/adafruit18-overlay.dts  | 11 +++++++++--
+ arch/arm/boot/dts/overlays/sainsmart18-overlay.dts | 10 ++++++++--
+ 3 files changed, 30 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -267,6 +267,13 @@ Info:   Overlay for the SPI-connected Ad
+ Load:   dtoverlay=adafruit18,<param>=<val>
+ Params: green                   Use the adafruit18_green variant.
+         rotate                  Display rotation {0,90,180,270}
++        speed                   SPI bus speed in Hz (default 4000000)
++        fps                     Display frame rate in Hz
++        bgr                     Enable BGR mode (default on)
++        debug                   Debug output level {0-7}
++        dc_pin                  GPIO pin for D/C (default 24)
++        reset_pin               GPIO pin for RESET (default 25)
++        led_pin                 GPIO used to control backlight (default 18)
+ Name:   adau1977-adc
+@@ -2271,6 +2278,12 @@ Info:   Overlay for the SPI-connected Sa
+         ST7735R chip).
+ Load:   dtoverlay=sainsmart18,<param>=<val>
+ Params: rotate                  Display rotation {0,90,180,270}
++        speed                   SPI bus speed in Hz (default 4000000)
++        fps                     Display frame rate in Hz
++        bgr                     Enable BGR mode (default on)
++        debug                   Debug output level {0-7}
++        dc_pin                  GPIO pin for D/C (default 24)
++        reset_pin               GPIO pin for RESET (default 25)
+ Name:   sc16is750-i2c
+--- a/arch/arm/boot/dts/overlays/adafruit18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adafruit18-overlay.dts
+@@ -33,7 +33,7 @@
+                               fps = <50>;
+                               height = <160>;
+                               width = <128>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+                               led-gpios = <&gpio 18 0>;
+                               bgr;
+@@ -44,6 +44,13 @@
+       __overrides__ {
+               green = <&af18>, "compatible=fbtft,adafruit18_green";
+-              rotate = <&af18>, "rotate:0";
++              speed     = <&af18>,"spi-max-frequency:0";
++              rotate    = <&af18>,"rotate:0";
++              fps       = <&af18>,"fps:0";
++              bgr       = <&af18>,"bgr?";
++              debug     = <&af18>,"debug:0";
++              dc_pin    = <&af18>,"dc-gpios:4";
++              reset_pin = <&af18>,"reset-gpios:4";
++              led_pin   = <&af18>,"led-gpios:4";
+       };
+ };
+--- a/arch/arm/boot/dts/overlays/sainsmart18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sainsmart18-overlay.dts
+@@ -33,7 +33,7 @@
+                               fps = <50>;
+                               height = <160>;
+                               width = <128>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+                               bgr;
+                               debug = <0>;
+@@ -42,6 +42,12 @@
+       };
+       __overrides__ {
+-              rotate = <&ss18>, "rotate:0";
++              speed     = <&ss18>,"spi-max-frequency:0";
++              rotate    = <&ss18>,"rotate:0";
++              fps       = <&ss18>,"fps:0";
++              bgr       = <&ss18>,"bgr?";
++              debug     = <&ss18>,"debug:0";
++              dc_pin    = <&ss18>,"dc-gpios:4";
++              reset_pin = <&ss18>,"reset-gpios:4";
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0969-rpivid_h265-Fix-width-height-typo.patch b/target/linux/bcm27xx/patches-5.4/950-0969-rpivid_h265-Fix-width-height-typo.patch
new file mode 100644 (file)
index 0000000..3aeb6e4
--- /dev/null
@@ -0,0 +1,21 @@
+From 3effc5ad6a017d4523158e04d2543a42def1744f Mon Sep 17 00:00:00 2001
+From: popcornmix <popcornmix@gmail.com>
+Date: Mon, 21 Sep 2020 14:02:44 +0100
+Subject: [PATCH] rpivid_h265: Fix width/height typo
+
+Signed-off-by: popcornmix <popcornmix@gmail.com>
+---
+ drivers/staging/media/rpivid/rpivid_h265.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/media/rpivid/rpivid_h265.c
++++ b/drivers/staging/media/rpivid/rpivid_h265.c
+@@ -2178,7 +2178,7 @@ static int rpivid_h265_start(struct rpiv
+       if (w > 4096)
+               w = 4096;
+       if (h == 0)
+-              w = 1088;
++              h = 1088;
+       if (h > 4096)
+               h = 4096;
+       wxh = w * h;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0970-overlays-Add-extra-CMA-sizes-up-to-512M.patch b/target/linux/bcm27xx/patches-5.4/950-0970-overlays-Add-extra-CMA-sizes-up-to-512M.patch
new file mode 100644 (file)
index 0000000..b9d46ac
--- /dev/null
@@ -0,0 +1,78 @@
+From 43d90a5beafa788c629c41a22623d82c10a9bbb9 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 21 Sep 2020 22:00:10 +0100
+Subject: [PATCH] overlays: Add extra CMA sizes (up to 512M)
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README          | 24 ++++++++++++++++++----
+ arch/arm/boot/dts/overlays/cma-overlay.dts |  4 ++++
+ 2 files changed, 24 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -582,7 +582,11 @@ Name:   cma
+ Info:   Set custom CMA sizes, only use if you know what you are doing, might
+         clash with other overlays like vc4-fkms-v3d and vc4-kms-v3d.
+ Load:   dtoverlay=cma,<param>=<val>
+-Params: cma-256                 CMA is 256MB (needs 1GB)
++Params: cma-512                 CMA is 512MB (needs 1GB)
++        cma-448                 CMA is 448MB (needs 1GB)
++        cma-384                 CMA is 384MB (needs 1GB)
++        cma-320                 CMA is 320MB (needs 1GB)
++        cma-256                 CMA is 256MB (needs 1GB)
+         cma-192                 CMA is 192MB (needs 1GB)
+         cma-128                 CMA is 128MB
+         cma-96                  CMA is 96MB
+@@ -2892,7 +2896,11 @@ Name:   vc4-fkms-v3d
+ Info:   Enable Eric Anholt's DRM VC4 V3D driver on top of the dispmanx
+         display stack.
+ Load:   dtoverlay=vc4-fkms-v3d,<param>
+-Params: cma-256                 CMA is 256MB (needs 1GB)
++Params: cma-512                 CMA is 512MB (needs 1GB)
++        cma-448                 CMA is 448MB (needs 1GB)
++        cma-384                 CMA is 384MB (needs 1GB)
++        cma-320                 CMA is 320MB (needs 1GB)
++        cma-256                 CMA is 256MB (needs 1GB)
+         cma-192                 CMA is 192MB (needs 1GB)
+         cma-128                 CMA is 128MB
+         cma-96                  CMA is 96MB
+@@ -2911,7 +2919,11 @@ Params: <None>
+ Name:   vc4-kms-v3d
+ Info:   Enable Eric Anholt's DRM VC4 HDMI/HVS/V3D driver.
+ Load:   dtoverlay=vc4-kms-v3d,<param>
+-Params: cma-256                 CMA is 256MB (needs 1GB)
++Params: cma-512                 CMA is 512MB (needs 1GB)
++        cma-448                 CMA is 448MB (needs 1GB)
++        cma-384                 CMA is 384MB (needs 1GB)
++        cma-320                 CMA is 320MB (needs 1GB)
++        cma-256                 CMA is 256MB (needs 1GB)
+         cma-192                 CMA is 192MB (needs 1GB)
+         cma-128                 CMA is 128MB
+         cma-96                  CMA is 96MB
+@@ -2925,7 +2937,11 @@ Params: cma-256                 CMA is 2
+ Name:   vc4-kms-v3d-pi4
+ Info:   Enable Eric Anholt's DRM VC4 HDMI/HVS/V3D driver for Pi4.
+ Load:   dtoverlay=vc4-kms-v3d-pi4,<param>
+-Params: cma-256                 CMA is 256MB
++Params: cma-512                 CMA is 512MB
++        cma-448                 CMA is 448MB
++        cma-384                 CMA is 384MB
++        cma-320                 CMA is 320MB
++        cma-256                 CMA is 256MB
+         cma-192                 CMA is 192MB
+         cma-128                 CMA is 128MB
+         cma-96                  CMA is 96MB
+--- a/arch/arm/boot/dts/overlays/cma-overlay.dts
++++ b/arch/arm/boot/dts/overlays/cma-overlay.dts
+@@ -21,6 +21,10 @@
+       };
+       __overrides__ {
++              cma-512 = <&frag0>,"size:0=",<0x20000000>;
++              cma-448 = <&frag0>,"size:0=",<0x1c000000>;
++              cma-384 = <&frag0>,"size:0=",<0x18000000>;
++              cma-320 = <&frag0>,"size:0=",<0x14000000>;
+               cma-256 = <&frag0>,"size:0=",<0x10000000>;
+               cma-192 = <&frag0>,"size:0=",<0xC000000>;
+               cma-128 = <&frag0>,"size:0=",<0x8000000>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0971-overlays-Add-note-to-BCM2711-overlays.patch b/target/linux/bcm27xx/patches-5.4/950-0971-overlays-Add-note-to-BCM2711-overlays.patch
new file mode 100644 (file)
index 0000000..3cf76d0
--- /dev/null
@@ -0,0 +1,150 @@
+From b2e311257e8c06f5d39004515c4adb65bb4fad3f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 21 Sep 2020 22:09:40 +0100
+Subject: [PATCH] overlays: Add note to BCM2711 overlays
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README | 32 +++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1403,7 +1403,7 @@ Load:   <Deprecated>
+ Name:   i2c3
+-Info:   Enable the i2c3 bus
++Info:   Enable the i2c3 bus. BCM2711 only.
+ Load:   dtoverlay=i2c3,<param>
+ Params: pins_2_3                Use GPIOs 2 and 3
+         pins_4_5                Use GPIOs 4 and 5 (default)
+@@ -1412,7 +1412,7 @@ Params: pins_2_3                Use GPIO
+ Name:   i2c4
+-Info:   Enable the i2c4 bus
++Info:   Enable the i2c4 bus. BCM2711 only.
+ Load:   dtoverlay=i2c4,<param>
+ Params: pins_6_7                Use GPIOs 6 and 7
+         pins_8_9                Use GPIOs 8 and 9 (default)
+@@ -1421,7 +1421,7 @@ Params: pins_6_7                Use GPIO
+ Name:   i2c5
+-Info:   Enable the i2c5 bus
++Info:   Enable the i2c5 bus. BCM2711 only.
+ Load:   dtoverlay=i2c5,<param>
+ Params: pins_10_11              Use GPIOs 10 and 11
+         pins_12_13              Use GPIOs 12 and 13 (default)
+@@ -1430,7 +1430,7 @@ Params: pins_10_11              Use GPIO
+ Name:   i2c6
+-Info:   Enable the i2c6 bus
++Info:   Enable the i2c6 bus. BCM2711 only.
+ Load:   dtoverlay=i2c6,<param>
+ Params: pins_0_1                Use GPIOs 0 and 1
+         pins_22_23              Use GPIOs 22 and 23 (default)
+@@ -2582,7 +2582,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi3-1cs
+ Info:   Enables spi3 with a single chip select (CS) line and associated spidev
+         dev node. The gpio pin number for the CS line and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi3-1cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 0 - BCM SPI3_CE0).
+         cs0_spidev              Set to 'off' to prevent the creation of a
+@@ -2593,7 +2593,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi3-2cs
+ Info:   Enables spi3 with two chip select (CS) lines and associated spidev
+         dev nodes. The gpio pin numbers for the CS lines and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi3-2cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 0 - BCM SPI3_CE0).
+         cs1_pin                 GPIO pin for CS1 (default 24 - BCM SPI3_CE1).
+@@ -2608,7 +2608,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi4-1cs
+ Info:   Enables spi4 with a single chip select (CS) line and associated spidev
+         dev node. The gpio pin number for the CS line and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi4-1cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 4 - BCM SPI4_CE0).
+         cs0_spidev              Set to 'off' to prevent the creation of a
+@@ -2619,7 +2619,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi4-2cs
+ Info:   Enables spi4 with two chip select (CS) lines and associated spidev
+         dev nodes. The gpio pin numbers for the CS lines and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi4-2cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 4 - BCM SPI4_CE0).
+         cs1_pin                 GPIO pin for CS1 (default 25 - BCM SPI4_CE1).
+@@ -2634,7 +2634,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi5-1cs
+ Info:   Enables spi5 with a single chip select (CS) line and associated spidev
+         dev node. The gpio pin numbers for the CS lines and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi5-1cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 12 - BCM SPI5_CE0).
+         cs0_spidev              Set to 'off' to prevent the creation of a
+@@ -2645,7 +2645,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi5-2cs
+ Info:   Enables spi5 with two chip select (CS) lines and associated spidev
+         dev nodes. The gpio pin numbers for the CS lines and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi5-2cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 12 - BCM SPI5_CE0).
+         cs1_pin                 GPIO pin for CS1 (default 26 - BCM SPI5_CE1).
+@@ -2660,7 +2660,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi6-1cs
+ Info:   Enables spi6 with a single chip select (CS) line and associated spidev
+         dev node. The gpio pin number for the CS line and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi6-1cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 18 - BCM SPI6_CE0).
+         cs0_spidev              Set to 'off' to prevent the creation of a
+@@ -2671,7 +2671,7 @@ Params: cs0_pin                 GPIO pin
+ Name:   spi6-2cs
+ Info:   Enables spi6 with two chip select (CS) lines and associated spidev
+         dev nodes. The gpio pin numbers for the CS lines and spidev device node
+-        creation are configurable.
++        creation are configurable. BCM2711 only.
+ Load:   dtoverlay=spi6-2cs,<param>=<val>
+ Params: cs0_pin                 GPIO pin for CS0 (default 18 - BCM SPI6_CE0).
+         cs1_pin                 GPIO pin for CS1 (default 27 - BCM SPI6_CE1).
+@@ -2843,25 +2843,25 @@ Params: txd1_pin                GPIO pin
+ Name:   uart2
+-Info:   Enable uart 2 on GPIOs 0-3
++Info:   Enable uart 2 on GPIOs 0-3. BCM2711 only.
+ Load:   dtoverlay=uart2,<param>
+ Params: ctsrts                  Enable CTS/RTS on GPIOs 2-3 (default off)
+ Name:   uart3
+-Info:   Enable uart 3 on GPIOs 4-7
++Info:   Enable uart 3 on GPIOs 4-7. BCM2711 only.
+ Load:   dtoverlay=uart3,<param>
+ Params: ctsrts                  Enable CTS/RTS on GPIOs 6-7 (default off)
+ Name:   uart4
+-Info:   Enable uart 4 on GPIOs 8-11
++Info:   Enable uart 4 on GPIOs 8-11. BCM2711 only.
+ Load:   dtoverlay=uart4,<param>
+ Params: ctsrts                  Enable CTS/RTS on GPIOs 10-11 (default off)
+ Name:   uart5
+-Info:   Enable uart 5 on GPIOs 12-15
++Info:   Enable uart 5 on GPIOs 12-15. BCM2711 only.
+ Load:   dtoverlay=uart5,<param>
+ Params: ctsrts                  Enable CTS/RTS on GPIOs 14-15 (default off)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0972-overlays-adafruit18-sainsmart18-default-bgr-to-off.patch b/target/linux/bcm27xx/patches-5.4/950-0972-overlays-adafruit18-sainsmart18-default-bgr-to-off.patch
new file mode 100644 (file)
index 0000000..70e11f4
--- /dev/null
@@ -0,0 +1,53 @@
+From b9801549748233e71a5c0dd76351e02a125505b4 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 21 Sep 2020 20:45:46 +0100
+Subject: [PATCH] overlays: adafruit18,sainsmart18: default bgr to
+ off
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README                  | 4 ++--
+ arch/arm/boot/dts/overlays/adafruit18-overlay.dts  | 1 -
+ arch/arm/boot/dts/overlays/sainsmart18-overlay.dts | 1 -
+ 3 files changed, 2 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -269,7 +269,7 @@ Params: green                   Use the
+         rotate                  Display rotation {0,90,180,270}
+         speed                   SPI bus speed in Hz (default 4000000)
+         fps                     Display frame rate in Hz
+-        bgr                     Enable BGR mode (default on)
++        bgr                     Enable BGR mode (default off)
+         debug                   Debug output level {0-7}
+         dc_pin                  GPIO pin for D/C (default 24)
+         reset_pin               GPIO pin for RESET (default 25)
+@@ -2284,7 +2284,7 @@ Load:   dtoverlay=sainsmart18,<param>=<v
+ Params: rotate                  Display rotation {0,90,180,270}
+         speed                   SPI bus speed in Hz (default 4000000)
+         fps                     Display frame rate in Hz
+-        bgr                     Enable BGR mode (default on)
++        bgr                     Enable BGR mode (default off)
+         debug                   Debug output level {0-7}
+         dc_pin                  GPIO pin for D/C (default 24)
+         reset_pin               GPIO pin for RESET (default 25)
+--- a/arch/arm/boot/dts/overlays/adafruit18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/adafruit18-overlay.dts
+@@ -36,7 +36,6 @@
+                               reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+                               led-gpios = <&gpio 18 0>;
+-                              bgr;
+                               debug = <0>;
+                       };
+               };
+--- a/arch/arm/boot/dts/overlays/sainsmart18-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sainsmart18-overlay.dts
+@@ -35,7 +35,6 @@
+                               width = <128>;
+                               reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+-                              bgr;
+                               debug = <0>;
+                       };
+               };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0973-net-bcmgenet-Reset-RBUF-on-first-open.patch b/target/linux/bcm27xx/patches-5.4/950-0973-net-bcmgenet-Reset-RBUF-on-first-open.patch
new file mode 100644 (file)
index 0000000..b7f0ce0
--- /dev/null
@@ -0,0 +1,70 @@
+From 507c4d749a1bbc3eb5c364dda61ac6bf95026cf1 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 25 Sep 2020 15:07:23 +0100
+Subject: [PATCH] net: bcmgenet: Reset RBUF on first open
+
+If the RBUF logic is not reset when the kernel starts then there
+may be some data left over from any network boot loader. If the
+64-byte packet headers are enabled then this can be fatal.
+
+Extend bcmgenet_dma_disable to do perform the reset, but not when
+called from bcmgenet_resume in order to preserve a wake packet.
+
+N.B. This different handling of resume is just based on a hunch -
+why else wouldn't one reset the RBUF as well as the TBUF? If this
+isn't the case then it's easy to change the patch to make the RBUF
+reset unconditional.
+
+See: https://github.com/raspberrypi/linux/issues/3850
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -2790,7 +2790,7 @@ static void bcmgenet_set_hw_addr(struct
+ }
+ /* Returns a reusable dma control register value */
+-static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
++static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx)
+ {
+       u32 reg;
+       u32 dma_ctrl;
+@@ -2809,6 +2809,14 @@ static u32 bcmgenet_dma_disable(struct b
+       udelay(10);
+       bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH);
++      if (flush_rx) {
++          reg = bcmgenet_rbuf_ctrl_get(priv);
++          bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0));
++          udelay(10);
++          bcmgenet_rbuf_ctrl_set(priv, reg);
++          udelay(10);
++      }
++
+       return dma_ctrl;
+ }
+@@ -2910,8 +2918,8 @@ static int bcmgenet_open(struct net_devi
+               bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+       }
+-      /* Disable RX/TX DMA and flush TX queues */
+-      dma_ctrl = bcmgenet_dma_disable(priv);
++      /* Disable RX/TX DMA and flush TX and RX queues */
++      dma_ctrl = bcmgenet_dma_disable(priv, true);
+       /* Reinitialize TDMA and RDMA and SW housekeeping */
+       ret = bcmgenet_init_dma(priv);
+@@ -3671,7 +3679,7 @@ static int bcmgenet_resume(struct device
+               bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
+       /* Disable RX/TX DMA and flush TX queues */
+-      dma_ctrl = bcmgenet_dma_disable(priv);
++      dma_ctrl = bcmgenet_dma_disable(priv, false);
+       /* Reinitialize TDMA and RDMA and SW housekeeping */
+       ret = bcmgenet_init_dma(priv);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0974-ASoC-cs42xx8-Only-define-cs42xx8_of_match-once.patch b/target/linux/bcm27xx/patches-5.4/950-0974-ASoC-cs42xx8-Only-define-cs42xx8_of_match-once.patch
new file mode 100644 (file)
index 0000000..1c8e4d6
--- /dev/null
@@ -0,0 +1,43 @@
+From e84f00c45ad064f1503d2eb03d7600e59744f0e6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 29 Sep 2020 15:03:34 +0100
+Subject: [PATCH] ASoC: cs42xx8: Only define cs42xx8_of_match once
+
+cs42xx8.c exports cs42xx8_of_match, so there's no need to redefine it
+in cs42xx8-i2c.c - doing so breaks linking when loadable module
+support is disabled. It would be tidy to use the exported match table
+in cs42xx8.c's of_match_table member, but an imported symbol can't be
+used in a module's MODULE_DEVICE_TABLE declaration. Instead, rename
+the duplicated declarations so as not to clash.
+
+See: https://github.com/raspberrypi/linux/issues/3873
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ sound/soc/codecs/cs42xx8-i2c.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/sound/soc/codecs/cs42xx8-i2c.c
++++ b/sound/soc/codecs/cs42xx8-i2c.c
+@@ -45,18 +45,18 @@ static struct i2c_device_id cs42xx8_i2c_
+ };
+ MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
+-const struct of_device_id cs42xx8_of_match[] = {
++const struct of_device_id cs42xx8_i2c_of_match[] = {
+       { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
+       { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
+       { /* sentinel */ }
+ };
+-MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
++MODULE_DEVICE_TABLE(of, cs42xx8_i2c_of_match);
+ static struct i2c_driver cs42xx8_i2c_driver = {
+       .driver = {
+               .name = "cs42xx8",
+               .pm = &cs42xx8_pm,
+-              .of_match_table = cs42xx8_of_match,
++              .of_match_table = cs42xx8_i2c_of_match,
+       },
+       .probe = cs42xx8_i2c_probe,
+       .remove = cs42xx8_i2c_remove,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0975-staging-bcm2835-codec-Use-a-define-the-completion-ti.patch b/target/linux/bcm27xx/patches-5.4/950-0975-staging-bcm2835-codec-Use-a-define-the-completion-ti.patch
new file mode 100644 (file)
index 0000000..f85baf2
--- /dev/null
@@ -0,0 +1,35 @@
+From 7ad713e695d67b78b3cb69927d099a29593444b1 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 30 Sep 2020 12:12:32 +0100
+Subject: [PATCH] staging: bcm2835-codec: Use a define the completion
+ timeout
+
+Hiding a use of "HZ" as a timeout is a little nasty.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c        | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -89,6 +89,9 @@ static const char * const components[] =
+       "ril.isp",
+ };
++/* Timeout for stop_streaming to allow all buffers to return */
++#define COMPLETE_TIMEOUT (2 * HZ)
++
+ #define MIN_W         32
+ #define MIN_H         32
+ #define MAX_W         1920
+@@ -2366,7 +2369,8 @@ static void bcm2835_codec_stop_streaming
+       while (atomic_read(&port->buffers_with_vpu)) {
+               v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
+                        __func__, atomic_read(&port->buffers_with_vpu));
+-              ret = wait_for_completion_timeout(&ctx->frame_cmplt, HZ);
++              ret = wait_for_completion_timeout(&ctx->frame_cmplt,
++                                                COMPLETE_TIMEOUT);
+               if (ret <= 0) {
+                       v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
+                                __func__,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0976-staging-bcm2835-codec-Correct-buffer-number-change-o.patch b/target/linux/bcm27xx/patches-5.4/950-0976-staging-bcm2835-codec-Correct-buffer-number-change-o.patch
new file mode 100644 (file)
index 0000000..c0193cb
--- /dev/null
@@ -0,0 +1,30 @@
+From 96f4d69496b483b8eb65dc4602d5cb96844f6647 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 30 Sep 2020 12:13:44 +0100
+Subject: [PATCH] staging: bcm2835-codec: Correct buffer number
+ change on start streaming
+
+"cac8c90 staging: vc04_service: codec: Allow start_streaming to update
+the buffernum" allowed the number of buffers configured to be decreased
+as well as increased, but there is no requirement for all buffers to
+have been queued when start_streaming is called.
+
+Only allow increasing the buffernum.
+
+Fixes: "cac8c90 staging: vc04_service: codec: Allow start_streaming to update the buffernum"
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c    | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -2290,7 +2290,7 @@ static int bcm2835_codec_start_streaming
+       if (count < port->minimum_buffer.num)
+               count = port->minimum_buffer.num;
+-      if (port->current_buffer.num != count + 1) {
++      if (port->current_buffer.num < count + 1) {
+               v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, buffer count changed %u to %u\n",
+                        __func__, ctx, port->current_buffer.num, count + 1);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0977-USB-gadget-f_hid-avoid-crashes-and-log-spam.patch b/target/linux/bcm27xx/patches-5.4/950-0977-USB-gadget-f_hid-avoid-crashes-and-log-spam.patch
new file mode 100644 (file)
index 0000000..1fe685c
--- /dev/null
@@ -0,0 +1,56 @@
+From 22198e801db7542c59098a75bdab120bcbc42652 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 30 Sep 2020 19:23:43 +0100
+Subject: [PATCH] USB: gadget: f_hid: avoid crashes and log spam
+
+Disconnecting and reconnecting the USB cable can lead to crashes and a
+variety of kernel log spam. Try to fix or minimise both.
+
+See: https://github.com/raspberrypi/linux/issues/3870
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/usb/gadget/function/f_hid.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -344,6 +344,11 @@ static ssize_t f_hidg_write(struct file
+       spin_lock_irqsave(&hidg->write_spinlock, flags);
++      if (!hidg->req) {
++              spin_unlock_irqrestore(&hidg->write_spinlock, flags);
++              return -ESHUTDOWN;
++      }
++
+ #define WRITE_COND (!hidg->write_pending)
+ try_again:
+       /* write queue */
+@@ -364,7 +369,13 @@ try_again:
+       count  = min_t(unsigned, count, hidg->report_length);
+       spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+-      status = copy_from_user(req->buf, buffer, count);
++      if (req) {
++              status = copy_from_user(req->buf, buffer, count);
++      } else {
++              ERROR(hidg->func.config->cdev, "hidg->req is NULL\n");
++              status = -ESHUTDOWN;
++              goto release_write_pending;
++      }
+       if (status != 0) {
+               ERROR(hidg->func.config->cdev,
+@@ -393,6 +404,11 @@ try_again:
+       spin_unlock_irqrestore(&hidg->write_spinlock, flags);
++      if (!hidg->in_ep->enabled) {
++              ERROR(hidg->func.config->cdev, "in_ep is disabled\n");
++              status = -ESHUTDOWN;
++              goto release_write_pending;
++      }
+       status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
+       if (status < 0) {
+               ERROR(hidg->func.config->cdev,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0978-Update-hy28b-overlay.dts.patch b/target/linux/bcm27xx/patches-5.4/950-0978-Update-hy28b-overlay.dts.patch
new file mode 100644 (file)
index 0000000..48efb5a
--- /dev/null
@@ -0,0 +1,21 @@
+From 8c997be099769362cb201d360ad57b639e799e9e Mon Sep 17 00:00:00 2001
+From: newbloke82 <39644602+newbloke82@users.noreply.github.com>
+Date: Thu, 1 Oct 2020 19:16:35 +0200
+Subject: [PATCH] Update hy28b-overlay.dts
+
+My hy28b TFT stopped working on upgrade to 5.4 kernel.  I had a whitescreen but no obvious errors when using 'sudo vcdbg log msg' or 'dmesg'.  Both /dev/fb0 and /dev/fb1 were present.  Followed this article on waveshare32b that 'reset_gpios needed to be 0 0 1 instead of 0 0 0' (https://forum.armbian.com/topic/13233-any-clues-for-the-creation-of-a-dtoverlay-for-fbtft-on-54y/).  I applied a similar change to this dts file and compiled a new dtbo: 'dtc -O dtb -o hy28b.dtbo hy28b-overlay.dts'.  Fixed my issue - may help others?  I got from the 5.4 upgrade thread that other tft users are having issues with small tfts... https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=269769&p=1706597&hilit=gpio#p1706597
+---
+ arch/arm/boot/dts/overlays/hy28b-overlay.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/hy28b-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28b-overlay.dts
+@@ -61,7 +61,7 @@
+                               fps = <50>;
+                               buswidth = <8>;
+                               startbyte = <0x70>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               led-gpios = <&gpio 18 1>;
+                               gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7";
diff --git a/target/linux/bcm27xx/patches-5.4/950-0979-overlays-Update-display-GPIO-declarations.patch b/target/linux/bcm27xx/patches-5.4/950-0979-overlays-Update-display-GPIO-declarations.patch
new file mode 100644 (file)
index 0000000..9b3cc5d
--- /dev/null
@@ -0,0 +1,170 @@
+From 0e81e4689a34e3f413ef403e0d801970d324c5b2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 2 Oct 2020 10:06:49 +0100
+Subject: [PATCH] overlays: Update display GPIO declarations
+
+The 5.4 kernel changes the way a number of display drivers use GPIOs.
+That change has exposed flaws/broken a number of display overlays, so
+after a trickle of single-display patches this is a best-guess attempt
+to fix the remainder. As none of these changes have been tested on real
+displays there is a possibility that this either doesn't fix the
+problem or even breaks something that was working - apologies if that
+is the case.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/goodix-overlay.dts       | 2 +-
+ arch/arm/boot/dts/overlays/hy28a-overlay.dts        | 2 +-
+ arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts   | 2 +-
+ arch/arm/boot/dts/overlays/media-center-overlay.dts | 6 +++---
+ arch/arm/boot/dts/overlays/mz61581-overlay.dts      | 2 +-
+ arch/arm/boot/dts/overlays/piscreen-overlay.dts     | 4 ++--
+ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts   | 4 ++--
+ arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts   | 2 +-
+ arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts  | 2 +-
+ arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts  | 2 +-
+ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts    | 4 ++--
+ 11 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/goodix-overlay.dts
++++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts
+@@ -31,7 +31,7 @@
+                               interrupt-parent = <&gpio>;
+                               interrupts = <4 2>; // high-to-low edge triggered
+                               irq-gpios = <&gpio 4 0>; // Pin7 on GPIO header
+-                              reset-gpios = <&gpio 17 0>; // Pin11 on GPIO header
++                              reset-gpios = <&gpio 17 1>; // Pin11 on GPIO header
+                       };
+               };
+       };
+--- a/arch/arm/boot/dts/overlays/hy28a-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28a-overlay.dts
+@@ -61,7 +61,7 @@
+                               fps = <50>;
+                               buswidth = <8>;
+                               startbyte = <0x70>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               led-gpios = <&gpio 18 1>;
+                               debug = <0>;
+                       };
+--- a/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
++++ b/arch/arm/boot/dts/overlays/hy28b-2017-overlay.dts
+@@ -61,7 +61,7 @@
+                               fps = <50>;
+                               buswidth = <8>;
+                               startbyte = <0x70>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               led-gpios = <&gpio 18 1>;
+                               init = <0x10000e5 0x78F0
+--- a/arch/arm/boot/dts/overlays/media-center-overlay.dts
++++ b/arch/arm/boot/dts/overlays/media-center-overlay.dts
+@@ -53,9 +53,9 @@
+                               bgr;
+                               fps = <30>;
+                               buswidth = <8>;
+-                              reset-gpios = <&gpio 23 0>;
++                              reset-gpios = <&gpio 23 1>;
+                               dc-gpios = <&gpio 24 0>;
+-                              led-gpios = <&gpio 12 1>;
++                              led-gpios = <&gpio 12 0>;
+                               debug = <0>;
+                       };
+@@ -66,7 +66,7 @@
+                               spi-max-frequency = <2000000>;
+                               interrupts = <25 2>; /* high-to-low edge triggered */
+                               interrupt-parent = <&gpio>;
+-                              pendown-gpio = <&gpio 25 0>;
++                              pendown-gpio = <&gpio 25 1>;
+                               ti,x-plate-ohms = /bits/ 16 <60>;
+                               ti,pressure-max = /bits/ 16 <255>;
+                       };
+--- a/arch/arm/boot/dts/overlays/mz61581-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mz61581-overlay.dts
+@@ -65,7 +65,7 @@
+                               buswidth = <8>;
+                               txbuflen = <32768>;
+-                              reset-gpios = <&gpio 15 0>;
++                              reset-gpios = <&gpio 15 1>;
+                               dc-gpios = <&gpio 25 0>;
+                               led-gpios = <&gpio 18 0>;
+--- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts
+@@ -59,9 +59,9 @@
+                               fps = <30>;
+                               buswidth = <8>;
+                               regwidth = <16>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+-                              led-gpios = <&gpio 22 1>;
++                              led-gpios = <&gpio 22 0>;
+                               debug = <0>;
+                               init = <0x10000b0 0x00
+--- a/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
++++ b/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts
+@@ -59,9 +59,9 @@
+                               buswidth = <8>;
+                               regwidth = <16>;
+                               txbuflen = <32768>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+-                              led-gpios = <&gpio 22 1>;
++                              led-gpios = <&gpio 22 0>;
+                               debug = <0>;
+                                 init = <0x10000b0 0x00
+--- a/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/sh1106-spi-overlay.dts
+@@ -59,7 +59,7 @@
+                               rotate = <0>;
+                               fps = <25>;
+                               buswidth = <8>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+                               debug = <0>;
+--- a/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1306-spi-overlay.dts
+@@ -59,7 +59,7 @@
+                               rotate = <0>;
+                               fps = <25>;
+                               buswidth = <8>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+                               debug = <0>;
+--- a/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ssd1351-spi-overlay.dts
+@@ -59,7 +59,7 @@
+                               rotate = <0>;
+                               fps = <25>;
+                               buswidth = <8>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+                               debug = <0>;
+--- a/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
++++ b/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts
+@@ -85,9 +85,9 @@
+                               fps = <20>;
+                               bgr;
+                               buswidth = <8>;
+-                              reset-gpios = <&gpio 25 0>;
++                              reset-gpios = <&gpio 25 1>;
+                               dc-gpios = <&gpio 24 0>;
+-                              led-gpios = <&gpio 18 1>;
++                              led-gpios = <&gpio 18 0>;
+                               debug = <0>;
+                               init = <0x10000B0 0x80
diff --git a/target/linux/bcm27xx/patches-5.4/950-0980-SQUASH-USB-gadget-f_hid-remove-more-spam.patch b/target/linux/bcm27xx/patches-5.4/950-0980-SQUASH-USB-gadget-f_hid-remove-more-spam.patch
new file mode 100644 (file)
index 0000000..3f199cf
--- /dev/null
@@ -0,0 +1,26 @@
+From 5018dc559136e2bca24973e71ed8747adf0f37f3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 5 Oct 2020 15:41:15 +0100
+Subject: [PATCH] SQUASH: USB: gadget: f_hid: remove more spam
+
+Tidying up the previous patch to this file dropped the deletion of a
+particularly noisy error message. Restore its removal.
+
+See: https://github.com/raspberrypi/linux/issues/3870
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/usb/gadget/function/f_hid.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -411,8 +411,6 @@ try_again:
+       }
+       status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
+       if (status < 0) {
+-              ERROR(hidg->func.config->cdev,
+-                      "usb_ep_queue error on int endpoint %zd\n", status);
+               goto release_write_pending;
+       } else {
+               status = count;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0981-overlays-Add-sd3078-to-the-i2c-rtc-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-0981-overlays-Add-sd3078-to-the-i2c-rtc-overlay.patch
new file mode 100644 (file)
index 0000000..5df3d2d
--- /dev/null
@@ -0,0 +1,58 @@
+From 8688b06ae53d6f60adcdcfe3d58ad7ef0ed7dba0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 5 Oct 2020 16:10:26 +0100
+Subject: [PATCH] overlays: Add sd3078 to the i2c-rtc overlay
+
+Add support for the SD3078 RTC to the i2c-rtc overlay.
+
+See: https://github.com/raspberrypi/linux/issues/3881
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README              |  2 ++
+ arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 16 ++++++++++++++++
+ 2 files changed, 18 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1232,6 +1232,8 @@ Params: abx80x                  Select o
+         rv3028                  Select the Micro Crystal RV3028 device
++        sd3078                  Select the ZXW Shenzhen whwave SD3078 device
++
+         addr                    Sets the address for the RTC. Note that the
+                                 device must be configured to use the specified
+                                 address.
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -220,6 +220,21 @@
+               };
+       };
++      fragment@14 {
++              target = <&i2c_arm>;
++              __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      sd3078: sd3078@32 {
++                              compatible = "whwave,sd3078";
++                              reg = <0x32>;
++                              status = "okay";
++                      };
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+0";
+               ds1307 = <0>,"+1";
+@@ -235,6 +250,7 @@
+               pcf2129 = <0>,"+11";
+               pcf85363 = <0>,"+12";
+               rv1805 = <0>,"+13";
++              sd3078 = <0>,"+14";
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
diff --git a/target/linux/bcm27xx/patches-5.4/950-0982-dwc_otg-initialise-sched_frame-for-periodic-QHs-that.patch b/target/linux/bcm27xx/patches-5.4/950-0982-dwc_otg-initialise-sched_frame-for-periodic-QHs-that.patch
new file mode 100644 (file)
index 0000000..2a12614
--- /dev/null
@@ -0,0 +1,33 @@
+From 2ae3859a69cecc2820f768f4d22022000e9f2e22 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Wed, 7 Oct 2020 15:09:29 +0100
+Subject: [PATCH] dwc_otg: initialise sched_frame for periodic QHs
+ that were parked
+
+If a periodic QH has no remaining QTDs, then it is removed from all
+periodic schedules. When re-adding, initialise the sched_frame and
+start_split_frame from the current value of the frame counter.
+
+See https://bugs.launchpad.net/raspbian/+bug/1819560
+and
+ https://github.com/raspberrypi/linux/issues/3883
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+@@ -689,7 +689,11 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * h
+                                    &qh->qh_list_entry);
+               //hcd->fiq_state->kick_np_queues = 1;
+       } else {
++              /* If the QH wasn't in a schedule, then sched_frame is stale. */
++              qh->sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd),
++                                                      SCHEDULE_SLOP);
+               status = schedule_periodic(hcd, qh);
++              qh->start_split_frame = qh->sched_frame;
+               if ( !hcd->periodic_qh_count ) {
+                       intr_mask.b.sofintr = 1;
+                       if (fiq_enable) {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0983-staging-bcm2835-camera-Replace-deprecated-V4L2_PIX_F.patch b/target/linux/bcm27xx/patches-5.4/950-0983-staging-bcm2835-camera-Replace-deprecated-V4L2_PIX_F.patch
new file mode 100644 (file)
index 0000000..f86566e
--- /dev/null
@@ -0,0 +1,30 @@
+From c46ee3d6fc36bcfe42ca860f8da85775f0b9cc6a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 8 Oct 2020 15:35:14 +0100
+Subject: [PATCH] staging: bcm2835-camera: Replace deprecated
+ V4L2_PIX_FMT_BGR32
+
+V4L2_PIX_FMT_BGR32 is deprecated as it is ambiguous over where
+the alpha byte is. Cheese/GStreamer appear to get it wrong for
+one, and qv4l2 gets red and blue swapped.
+
+Swap to the newer V4L2_PIX_FMT_BGRX32 format.
+
+https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=267736&p=1738912
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -175,7 +175,7 @@ static struct mmal_fmt formats[] = {
+               .ybbp = 1,
+               .remove_padding = 1,
+       }, {
+-              .fourcc = V4L2_PIX_FMT_BGR32,
++              .fourcc = V4L2_PIX_FMT_BGRX32,
+               .mmal = MMAL_ENCODING_BGRA,
+               .depth = 32,
+               .mmal_component = COMP_CAMERA,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0984-staging-bcm2835-codec-Replace-deprecated-V4L2_PIX_FM.patch b/target/linux/bcm27xx/patches-5.4/950-0984-staging-bcm2835-codec-Replace-deprecated-V4L2_PIX_FM.patch
new file mode 100644 (file)
index 0000000..2e6d04b
--- /dev/null
@@ -0,0 +1,27 @@
+From ed4adfd60c1495b864720e1f79b0b2a443447e38 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 8 Oct 2020 16:06:59 +0100
+Subject: [PATCH] staging: bcm2835-codec: Replace deprecated
+ V4L2_PIX_FMT_BGR32
+
+V4L2_PIX_FMT_BGR32 is deprecated as it is ambiguous over where
+the alpha byte is.
+
+Swap to the newer V4L2_PIX_FMT_BGRX32 format.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c    | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -207,7 +207,7 @@ static const struct bcm2835_codec_fmt su
+               .mmal_fmt               = MMAL_ENCODING_BGR24,
+               .size_multiplier_x2     = 2,
+       }, {
+-              .fourcc                 = V4L2_PIX_FMT_BGR32,
++              .fourcc                 = V4L2_PIX_FMT_BGRX32,
+               .depth                  = 32,
+               .bytesperline_align     = 32,
+               .flags                  = 0,
diff --git a/target/linux/bcm27xx/patches-5.4/950-0985-ARM-bcm2711-rpi.dts-Unlock-DMA-channels-9-10.patch b/target/linux/bcm27xx/patches-5.4/950-0985-ARM-bcm2711-rpi.dts-Unlock-DMA-channels-9-10.patch
new file mode 100644 (file)
index 0000000..8895a02
--- /dev/null
@@ -0,0 +1,33 @@
+From b10a49ab016ed9ac8f231845fb3e83fbf3505652 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 12 Oct 2020 14:36:35 +0100
+Subject: [PATCH] ARM: bcm2711-rpi.dts: Unlock DMA channels 9 & 10
+
+The downstream-specific override of the 32-bit DMA mask needlessly
+disables channels 9 and 10 - the VPU doesn't use them. This override
+is redundant, so delete it.
+
+See: https://github.com/raspberrypi/linux/issues/3896
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -246,13 +246,8 @@
+       };
+ };
+-&dma {
+-      /* The VPU firmware uses DMA channel 11 for VCHIQ */
+-      brcm,dma-channel-mask = <0x1f5>;
+-};
+-
+ &dma40 {
+-      /* The VPU firmware DMA channel 11 for VCHIQ */
++      /* The VPU firmware uses DMA channel 11 for VCHIQ */
+       brcm,dma-channel-mask = <0x7000>;
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0986-gpio-Add-gpio-fsm-driver.patch b/target/linux/bcm27xx/patches-5.4/950-0986-gpio-Add-gpio-fsm-driver.patch
new file mode 100644 (file)
index 0000000..7076026
--- /dev/null
@@ -0,0 +1,1182 @@
+From c31626a9e173f2b2e0adc4cb8bfbb86a958bafcd Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 30 Sep 2020 12:00:54 +0100
+Subject: [PATCH] gpio: Add gpio-fsm driver
+
+The gpio-fsm driver implements simple state machines that allow GPIOs
+to be controlled in response to inputs from other GPIOs - real and
+soft/virtual - and time delays. It can:
++ create dummy GPIOs for drivers that demand them,
++ drive multiple GPIOs from a single input, with optional delays,
++ add a debounce circuit to an input,
++ drive pattern sequences onto LEDs
+etc.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/gpio/Kconfig                |    9 +
+ drivers/gpio/Makefile               |    1 +
+ drivers/gpio/gpio-fsm.c             | 1103 +++++++++++++++++++++++++++
+ include/dt-bindings/gpio/gpio-fsm.h |   21 +
+ 4 files changed, 1134 insertions(+)
+ create mode 100644 drivers/gpio/gpio-fsm.c
+ create mode 100644 include/dt-bindings/gpio/gpio-fsm.h
+
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -1071,6 +1071,15 @@ config HTC_EGPIO
+         several HTC phones.  It provides basic support for input
+         pins, output pins, and irqs.
++config GPIO_FSM
++      tristate "GPIO FSM support"
++      help
++        The GPIO FSM driver allows the creation of state machines for
++        manipulating GPIOs (both real and virtual), with state transitions
++        triggered by GPIO edges or delays.
++
++        If unsure, say N.
++
+ config GPIO_JANZ_TTL
+       tristate "Janz VMOD-TTL Digital IO Module"
+       depends on MFD_JANZ_CMODIO
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -55,6 +55,7 @@ obj-$(CONFIG_GPIO_EP93XX)            += gpio-ep93x
+ obj-$(CONFIG_GPIO_EXAR)                       += gpio-exar.o
+ obj-$(CONFIG_GPIO_F7188X)             += gpio-f7188x.o
+ obj-$(CONFIG_GPIO_FTGPIO010)          += gpio-ftgpio010.o
++obj-$(CONFIG_GPIO_FSM)                        += gpio-fsm.o
+ obj-$(CONFIG_GPIO_GE_FPGA)            += gpio-ge.o
+ obj-$(CONFIG_GPIO_GPIO_MM)            += gpio-gpio-mm.o
+ obj-$(CONFIG_GPIO_GRGPIO)             += gpio-grgpio.o
+--- /dev/null
++++ b/drivers/gpio/gpio-fsm.c
+@@ -0,0 +1,1103 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ *  GPIO FSM driver
++ *
++ *  This driver implements simple state machines that allow real GPIOs to be
++ *  controlled in response to inputs from other GPIOs - real and soft/virtual -
++ *  and time delays. It can:
++ *  + create dummy GPIOs for drivers that demand them
++ *  + drive multiple GPIOs from a single input,  with optional delays
++ *  + add a debounce circuit to an input
++ *  + drive pattern sequences onto LEDs
++ *  etc.
++ *
++ *  Copyright (C) 2020 Raspberry Pi (Trading) Ltd.
++ */
++
++#include <linux/err.h>
++#include <linux/gpio.h>
++#include <linux/gpio/driver.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <dt-bindings/gpio/gpio-fsm.h>
++
++#define MODULE_NAME "gpio-fsm"
++
++#define GF_IO_TYPE(x) ((u32)(x) & 0xffff)
++#define GF_IO_INDEX(x) ((u32)(x) >> 16)
++
++enum {
++      SIGNAL_GPIO,
++      SIGNAL_SOFT
++};
++
++enum {
++      INPUT_GPIO,
++      INPUT_SOFT
++};
++
++enum {
++      SYM_UNDEFINED,
++      SYM_NAME,
++      SYM_SET,
++      SYM_START,
++      SYM_SHUTDOWN,
++
++      SYM_MAX
++};
++
++struct soft_gpio {
++      int dir;
++      int value;
++};
++
++struct input_gpio_state {
++      struct gpio_fsm *gf;
++      struct gpio_desc  *desc;
++      struct fsm_state *target;
++      int index;
++      int value;
++      int irq;
++      bool enabled;
++      bool active_low;
++};
++
++struct gpio_event {
++      int index;
++      int value;
++      struct fsm_state *target;
++};
++
++struct symtab_entry {
++      const char *name;
++      void *value;
++      struct symtab_entry *next;
++};
++
++struct output_signal {
++      u8 type;
++      u8 value;
++      u16 index;
++};
++
++struct fsm_state {
++      const char *name;
++      struct output_signal *signals;
++      struct gpio_event *gpio_events;
++      struct gpio_event *soft_events;
++      struct fsm_state *delay_target;
++      struct fsm_state *shutdown_target;
++      unsigned int num_signals;
++      unsigned int num_gpio_events;
++      unsigned int num_soft_events;
++      unsigned int delay_ms;
++      unsigned int shutdown_ms;
++};
++
++struct gpio_fsm {
++      struct gpio_chip gc;
++      struct device *dev;
++      spinlock_t spinlock;
++      struct work_struct work;
++      struct timer_list timer;
++      wait_queue_head_t shutdown_event;
++      struct fsm_state *states;
++      struct input_gpio_state *input_gpio_states;
++      struct gpio_descs *input_gpios;
++      struct gpio_descs *output_gpios;
++      struct soft_gpio *soft_gpios;
++      struct fsm_state *start_state;
++      struct fsm_state *shutdown_state;
++      unsigned int num_states;
++      unsigned int num_output_gpios;
++      unsigned int num_input_gpios;
++      unsigned int num_soft_gpios;
++      unsigned int shutdown_timeout_ms;
++      unsigned int shutdown_jiffies;
++
++      struct fsm_state *current_state;
++      struct fsm_state *next_state;
++      struct fsm_state *delay_target_state;
++      int delay_ms;
++      unsigned int debug;
++      bool shutting_down;
++      struct symtab_entry *symtab;
++};
++
++static struct symtab_entry *do_add_symbol(struct symtab_entry **symtab,
++                                        const char *name, void *value)
++{
++      struct symtab_entry **p = symtab;
++
++      while (*p && strcmp((*p)->name, name))
++              p = &(*p)->next;
++
++      if (*p) {
++              /* This is an existing symbol */
++              if ((*p)->value) {
++                      /* Already defined */
++                      if (value) {
++                              if ((uintptr_t)value < SYM_MAX)
++                                      return ERR_PTR(-EINVAL);
++                              else
++                                      return ERR_PTR(-EEXIST);
++                      }
++              } else {
++                      /* Undefined */
++                      (*p)->value = value;
++              }
++      } else {
++              /* This is a new symbol */
++              *p = kmalloc(sizeof(struct symtab_entry), GFP_KERNEL);
++              if (*p) {
++                      (*p)->name = name;
++                      (*p)->value = value;
++                      (*p)->next = NULL;
++              }
++      }
++      return *p;
++}
++
++static int add_symbol(struct symtab_entry **symtab,
++                    const char *name, void *value)
++{
++      struct symtab_entry *sym = do_add_symbol(symtab, name, value);
++
++      return PTR_ERR_OR_ZERO(sym);
++}
++
++static struct symtab_entry *get_symbol(struct symtab_entry **symtab,
++                                     const char *name)
++{
++      struct symtab_entry *sym = do_add_symbol(symtab, name, NULL);
++
++      if (IS_ERR(sym))
++              return NULL;
++      return sym;
++}
++
++static void free_symbols(struct symtab_entry **symtab)
++{
++      struct symtab_entry *sym = *symtab;
++      void *p;
++
++      *symtab = NULL;
++      while (sym) {
++              p = sym;
++              sym = sym->next;
++              kfree(p);
++      }
++}
++
++static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off)
++{
++      struct gpio_fsm *gf = gpiochip_get_data(gc);
++      struct soft_gpio *sg;
++
++      if (off >= gf->num_soft_gpios)
++              return -EINVAL;
++      sg = &gf->soft_gpios[off];
++
++      return sg->dir;
++}
++
++static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off)
++{
++      struct gpio_fsm *gf = gpiochip_get_data(gc);
++      struct soft_gpio *sg;
++
++      if (off >= gf->num_soft_gpios)
++              return -EINVAL;
++      sg = &gf->soft_gpios[off];
++
++      return sg->value;
++}
++
++static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
++                                 struct fsm_state *new_state)
++{
++      struct input_gpio_state *inp_state;
++      struct gpio_event *gp_ev;
++      struct fsm_state *state;
++      int i;
++
++      dev_dbg(gf->dev, "go_to_state(%s)\n",
++                new_state ? new_state->name : "<unset>");
++
++      spin_lock(&gf->spinlock);
++
++      if (gf->next_state) {
++              /* Something else has already requested a transition */
++              spin_unlock(&gf->spinlock);
++              return;
++      }
++
++      gf->next_state = new_state;
++      state = gf->current_state;
++      gf->delay_target_state = NULL;
++
++      if (state) {
++              /* Disarm any GPIO IRQs */
++              for (i = 0; i < state->num_gpio_events; i++) {
++                      gp_ev = &state->gpio_events[i];
++                      inp_state = &gf->input_gpio_states[gp_ev->index];
++                      inp_state->target = NULL;
++              }
++      }
++
++      spin_unlock(&gf->spinlock);
++
++      if (new_state)
++              schedule_work(&gf->work);
++}
++
++static void gpio_fsm_set_soft(struct gpio_fsm *gf,
++                              unsigned int off, int val)
++{
++      struct soft_gpio *sg = &gf->soft_gpios[off];
++      struct gpio_event *gp_ev;
++      struct fsm_state *state;
++      int i;
++
++      dev_dbg(gf->dev, "set(%d,%d)\n", off, val);
++      state = gf->current_state;
++      sg->value = val;
++      for (i = 0; i < state->num_soft_events; i++) {
++              gp_ev = &state->soft_events[i];
++              if (gp_ev->index == off && gp_ev->value == val) {
++                      if (gf->debug)
++                              dev_info(gf->dev,
++                                       "GF_SOFT %d->%d -> %s\n", gp_ev->index,
++                                       gp_ev->value, gp_ev->target->name);
++                      gpio_fsm_go_to_state(gf, gp_ev->target);
++                      break;
++              }
++      }
++}
++
++static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off)
++{
++      struct gpio_fsm *gf = gpiochip_get_data(gc);
++      struct soft_gpio *sg;
++
++      if (off >= gf->num_soft_gpios)
++              return -EINVAL;
++      sg = &gf->soft_gpios[off];
++      sg->dir = GPIOF_DIR_IN;
++
++      return 0;
++}
++
++static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off,
++                                     int value)
++{
++      struct gpio_fsm *gf = gpiochip_get_data(gc);
++      struct soft_gpio *sg;
++
++      if (off >= gf->num_soft_gpios)
++              return -EINVAL;
++      sg = &gf->soft_gpios[off];
++      sg->dir = GPIOF_DIR_OUT;
++      gpio_fsm_set_soft(gf, off, value);
++
++      return 0;
++}
++
++static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val)
++{
++      struct gpio_fsm *gf;
++
++      gf = gpiochip_get_data(gc);
++      if (off < gf->num_soft_gpios)
++              gpio_fsm_set_soft(gf, off, val);
++}
++
++static void gpio_fsm_enter_state(struct gpio_fsm *gf,
++                                 struct fsm_state *state)
++{
++      struct input_gpio_state *inp_state;
++      struct output_signal *signal;
++      struct gpio_event *event;
++      struct gpio_desc *gpiod;
++      struct soft_gpio *soft;
++      int value;
++      int i;
++
++      dev_dbg(gf->dev, "enter_state(%s)\n", state->name);
++
++      gf->current_state = state;
++
++      // 1. Apply any listed signals
++      for (i = 0; i < state->num_signals; i++) {
++              signal = &state->signals[i];
++
++              if (gf->debug)
++                      dev_info(gf->dev, "  set %s %d->%d\n",
++                               (signal->type == SIGNAL_GPIO) ? "GF_OUT" :
++                               "GF_SOFT",
++                               signal->index, signal->value);
++              switch (signal->type) {
++              case SIGNAL_GPIO:
++                      gpiod = gf->output_gpios->desc[signal->index];
++                      gpiod_set_value_cansleep(gpiod, signal->value);
++                      break;
++              case SIGNAL_SOFT:
++                      soft = &gf->soft_gpios[signal->index];
++                      gpio_fsm_set_soft(gf, signal->index, signal->value);
++                      break;
++              }
++      }
++
++      // 2. Exit if successfully reached shutdown state
++      if (gf->shutting_down && state == state->shutdown_target) {
++              wake_up(&gf->shutdown_event);
++              return;
++      }
++
++      // 3. Schedule a timer callback if shutting down
++      if (state->shutdown_target) {
++              // Remember the absolute shutdown time in case remove is called
++              // at a later time.
++              gf->shutdown_jiffies =
++                      jiffies + msecs_to_jiffies(state->shutdown_ms);
++
++              if (gf->shutting_down) {
++                      gf->delay_target_state = state->shutdown_target;
++                      gf->delay_ms = state->shutdown_ms;
++                      mod_timer(&gf->timer, gf->shutdown_jiffies);
++              }
++      }
++
++      // During shutdown, skip everything else
++      if (gf->shutting_down)
++              return;
++
++      // Otherwise record what the shutdown time would be
++      gf->shutdown_jiffies = jiffies + msecs_to_jiffies(state->shutdown_ms);
++
++      // 4. Check soft inputs for transitions to take
++      for (i = 0; i < state->num_soft_events; i++) {
++              event = &state->soft_events[i];
++              if (gf->soft_gpios[event->index].value == event->value) {
++                      if (gf->debug)
++                              dev_info(gf->dev,
++                                       "GF_SOFT %d=%d -> %s\n", event->index,
++                                       event->value, event->target->name);
++                      gpio_fsm_go_to_state(gf, event->target);
++                      return;
++              }
++      }
++
++      // 5. Check GPIOs for transitions to take, enabling the IRQs
++      for (i = 0; i < state->num_gpio_events; i++) {
++              event = &state->gpio_events[i];
++              inp_state = &gf->input_gpio_states[event->index];
++              inp_state->target = event->target;
++              inp_state->value = event->value;
++              inp_state->enabled = true;
++
++              value = gpiod_get_value(gf->input_gpios->desc[event->index]);
++
++              // Clear stale event state
++              disable_irq(inp_state->irq);
++
++              irq_set_irq_type(inp_state->irq,
++                               (inp_state->value ^ inp_state->active_low) ?
++                               IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING);
++              enable_irq(inp_state->irq);
++
++              if (value == event->value && inp_state->target) {
++                      if (gf->debug)
++                              dev_info(gf->dev,
++                                       "GF_IN %d=%d -> %s\n", event->index,
++                                       event->value, event->target->name);
++                      gpio_fsm_go_to_state(gf, event->target);
++                      return;
++              }
++      }
++
++      // 6. Schedule a timer callback if delay_target
++      if (state->delay_target) {
++              gf->delay_target_state = state->delay_target;
++              gf->delay_ms = state->delay_ms;
++              mod_timer(&gf->timer,
++                        jiffies + msecs_to_jiffies(state->delay_ms));
++      }
++}
++
++static void gpio_fsm_work(struct work_struct *work)
++{
++      struct input_gpio_state *inp_state;
++      struct fsm_state *new_state;
++      struct fsm_state *state;
++      struct gpio_event *gp_ev;
++      struct gpio_fsm *gf;
++      int i;
++
++      gf = container_of(work, struct gpio_fsm, work);
++      spin_lock(&gf->spinlock);
++      state = gf->current_state;
++      new_state = gf->next_state;
++      if (!new_state)
++              new_state = gf->delay_target_state;
++      gf->next_state = NULL;
++      gf->delay_target_state = NULL;
++      spin_unlock(&gf->spinlock);
++
++      if (state) {
++              /* Disable any enabled GPIO IRQs */
++              for (i = 0; i < state->num_gpio_events; i++) {
++                      gp_ev = &state->gpio_events[i];
++                      inp_state = &gf->input_gpio_states[gp_ev->index];
++                      if (inp_state->enabled) {
++                              inp_state->enabled = false;
++                              irq_set_irq_type(inp_state->irq,
++                                               IRQF_TRIGGER_NONE);
++                      }
++              }
++      }
++
++      if (new_state)
++              gpio_fsm_enter_state(gf, new_state);
++}
++
++static irqreturn_t gpio_fsm_gpio_irq_handler(int irq, void *dev_id)
++{
++      struct input_gpio_state *inp_state = dev_id;
++      struct gpio_fsm *gf = inp_state->gf;
++      struct fsm_state *target;
++
++      target = inp_state->target;
++      if (!target)
++              return IRQ_NONE;
++
++      /* If the IRQ has fired then the desired state _must_ have occurred */
++      inp_state->enabled = false;
++      irq_set_irq_type(inp_state->irq, IRQF_TRIGGER_NONE);
++      if (gf->debug)
++              dev_info(gf->dev, "GF_IN %d->%d -> %s\n",
++                       inp_state->index, inp_state->value, target->name);
++      gpio_fsm_go_to_state(gf, target);
++      return IRQ_HANDLED;
++}
++
++static void gpio_fsm_timer(struct timer_list *timer)
++{
++      struct gpio_fsm *gf = container_of(timer, struct gpio_fsm, timer);
++      struct fsm_state *target;
++
++      target = gf->delay_target_state;
++      if (!target)
++              return;
++
++      if (gf->debug)
++              dev_info(gf->dev, "GF_DELAY %d -> %s\n", gf->delay_ms,
++                       target->name);
++
++      gpio_fsm_go_to_state(gf, target);
++}
++
++int gpio_fsm_parse_signals(struct gpio_fsm *gf, struct fsm_state *state,
++                           struct property *prop)
++{
++      const __be32 *cells = prop->value;
++      struct output_signal *signal;
++      u32 io;
++      u32 type;
++      u32 index;
++      u32 value;
++      int ret = 0;
++      int i;
++
++      if (prop->length % 8) {
++              dev_err(gf->dev, "malformed set in state %s\n",
++                      state->name);
++              return -EINVAL;
++      }
++
++      state->num_signals = prop->length/8;
++      state->signals = devm_kcalloc(gf->dev, state->num_signals,
++                                    sizeof(struct output_signal),
++                                    GFP_KERNEL);
++      for (i = 0; i < state->num_signals; i++) {
++              signal = &state->signals[i];
++              io = be32_to_cpu(cells[0]);
++              type = GF_IO_TYPE(io);
++              index = GF_IO_INDEX(io);
++              value = be32_to_cpu(cells[1]);
++
++              if (type != GF_OUT && type != GF_SOFT) {
++                      dev_err(gf->dev,
++                              "invalid set type %d in state %s\n",
++                              type, state->name);
++                      ret = -EINVAL;
++                      break;
++              }
++              if (type == GF_OUT && index >= gf->num_output_gpios) {
++                      dev_err(gf->dev,
++                              "invalid GF_OUT number %d in state %s\n",
++                              index, state->name);
++                      ret = -EINVAL;
++                      break;
++              }
++              if (type == GF_SOFT && index >= gf->num_soft_gpios) {
++                      dev_err(gf->dev,
++                              "invalid GF_SOFT number %d in state %s\n",
++                              index, state->name);
++                      ret = -EINVAL;
++                      break;
++              }
++              if (value != 0 && value != 1) {
++                      dev_err(gf->dev,
++                              "invalid set value %d in state %s\n",
++                              value, state->name);
++                      ret = -EINVAL;
++                      break;
++              }
++              signal->type = (type == GF_OUT) ? SIGNAL_GPIO : SIGNAL_SOFT;
++              signal->index = index;
++              signal->value = value;
++              cells += 2;
++      }
++
++      return ret;
++}
++
++struct gpio_event *new_event(struct gpio_event **events, int *num_events)
++{
++      int num = ++(*num_events);
++      *events = krealloc(*events, num * sizeof(struct gpio_event),
++                         GFP_KERNEL);
++      return *events ? *events + (num - 1) : NULL;
++}
++
++int gpio_fsm_parse_events(struct gpio_fsm *gf, struct fsm_state *state,
++                          struct property *prop)
++{
++      const __be32 *cells = prop->value;
++      struct symtab_entry *sym;
++      int num_cells;
++      int ret = 0;
++      int i;
++
++      if (prop->length % 8) {
++              dev_err(gf->dev,
++                      "malformed transitions from state %s to state %s\n",
++                      state->name, prop->name);
++              return -EINVAL;
++      }
++
++      sym = get_symbol(&gf->symtab, prop->name);
++      num_cells = prop->length / 4;
++      i = 0;
++      while (i < num_cells) {
++              struct gpio_event *gp_ev;
++              u32 event, param;
++              u32 index;
++
++              event = be32_to_cpu(cells[i++]);
++              param = be32_to_cpu(cells[i++]);
++              index = GF_IO_INDEX(event);
++
++              switch (GF_IO_TYPE(event)) {
++              case GF_IN:
++                      if (index >= gf->num_input_gpios) {
++                              dev_err(gf->dev,
++                                      "invalid GF_IN %d in transitions from state %s to state %s\n",
++                                      index, state->name, prop->name);
++                              return -EINVAL;
++                      }
++                      if (param > 1) {
++                              dev_err(gf->dev,
++                                      "invalid GF_IN value %d in transitions from state %s to state %s\n",
++                                      param, state->name, prop->name);
++                              return -EINVAL;
++                      }
++                      gp_ev = new_event(&state->gpio_events,
++                                        &state->num_gpio_events);
++                      if (!gp_ev)
++                              return -ENOMEM;
++                      gp_ev->index = index;
++                      gp_ev->value = param;
++                      gp_ev->target = (struct fsm_state *)sym;
++                      break;
++
++              case GF_SOFT:
++                      if (index >= gf->num_soft_gpios) {
++                              dev_err(gf->dev,
++                                      "invalid GF_SOFT %d in transitions from state %s to state %s\n",
++                                      index, state->name, prop->name);
++                              return -EINVAL;
++                      }
++                      if (param > 1) {
++                              dev_err(gf->dev,
++                                      "invalid GF_SOFT value %d in transitions from state %s to state %s\n",
++                                      param, state->name, prop->name);
++                              return -EINVAL;
++                      }
++                      gp_ev = new_event(&state->soft_events,
++                                        &state->num_soft_events);
++                      if (!gp_ev)
++                              return -ENOMEM;
++                      gp_ev->index = index;
++                      gp_ev->value = param;
++                      gp_ev->target = (struct fsm_state *)sym;
++                      break;
++
++              case GF_DELAY:
++                      if (state->delay_target) {
++                              dev_err(gf->dev,
++                                      "state %s has multiple GF_DELAYs\n",
++                                      state->name);
++                              return -EINVAL;
++                      }
++                      state->delay_target = (struct fsm_state *)sym;
++                      state->delay_ms = param;
++                      break;
++
++              case GF_SHUTDOWN:
++                      if (state->shutdown_target == state) {
++                              dev_err(gf->dev,
++                                      "shutdown state %s has GF_SHUTDOWN\n",
++                                      state->name);
++                              return -EINVAL;
++                      } else if (state->shutdown_target) {
++                              dev_err(gf->dev,
++                                      "state %s has multiple GF_SHUTDOWNs\n",
++                                      state->name);
++                              return -EINVAL;
++                      }
++                      state->shutdown_target =
++                              (struct fsm_state *)sym;
++                      state->shutdown_ms = param;
++                      break;
++
++              default:
++                      dev_err(gf->dev,
++                              "invalid event %08x in transitions from state %s to state %s\n",
++                              event, state->name, prop->name);
++                      return -EINVAL;
++              }
++      }
++      if (i != num_cells) {
++              dev_err(gf->dev,
++                      "malformed transitions from state %s to state %s\n",
++                      state->name, prop->name);
++              return -EINVAL;
++      }
++
++      return ret;
++}
++
++int gpio_fsm_parse_state(struct gpio_fsm *gf,
++                         struct fsm_state *state,
++                         struct device_node *np)
++{
++      struct symtab_entry *sym;
++      struct property *prop;
++      int ret;
++
++      state->name = np->name;
++      ret = add_symbol(&gf->symtab, np->name, state);
++      if (ret) {
++              switch (ret) {
++              case -EINVAL:
++                      dev_err(gf->dev, "'%s' is not a valid state name\n",
++                              np->name);
++                      break;
++              case -EEXIST:
++                      dev_err(gf->dev, "state %s already defined\n",
++                              np->name);
++                      break;
++              default:
++                      dev_err(gf->dev, "error %d adding state %s symbol\n",
++                              ret, np->name);
++                      break;
++              }
++              return ret;
++      }
++
++      for_each_property_of_node(np, prop) {
++              sym = get_symbol(&gf->symtab, prop->name);
++              if (!sym) {
++                      ret = -ENOMEM;
++                      break;
++              }
++
++              switch ((uintptr_t)sym->value) {
++              case SYM_SET:
++                      ret = gpio_fsm_parse_signals(gf, state, prop);
++                      break;
++              case SYM_START:
++                      if (gf->start_state) {
++                              dev_err(gf->dev, "multiple start states\n");
++                              ret = -EINVAL;
++                      } else {
++                              gf->start_state = state;
++                      }
++                      break;
++              case SYM_SHUTDOWN:
++                      state->shutdown_target = state;
++                      gf->shutdown_state = state;
++                      break;
++              case SYM_NAME:
++                      /* Ignore */
++                      break;
++              default:
++                      /* A set of transition events to this state */
++                      ret = gpio_fsm_parse_events(gf, state, prop);
++                      break;
++              }
++      }
++
++      return ret;
++}
++
++static void dump_all(struct gpio_fsm *gf)
++{
++      int i, j;
++
++      dev_info(gf->dev, "Input GPIOs:\n");
++      for (i = 0; i < gf->num_input_gpios; i++)
++              dev_info(gf->dev, "  %d: %p\n", i,
++                       gf->input_gpios->desc[i]);
++
++      dev_info(gf->dev, "Output GPIOs:\n");
++      for (i = 0; i < gf->num_output_gpios; i++)
++              dev_info(gf->dev, "  %d: %p\n", i,
++                       gf->output_gpios->desc[i]);
++
++      dev_info(gf->dev, "Soft GPIOs:\n");
++      for (i = 0; i < gf->num_soft_gpios; i++)
++              dev_info(gf->dev, "  %d: %s %d\n", i,
++                       (gf->soft_gpios[i].dir == GPIOF_DIR_IN) ? "IN" : "OUT",
++                       gf->soft_gpios[i].value);
++
++      dev_info(gf->dev, "Start state: %s\n",
++               gf->start_state ? gf->start_state->name : "-");
++
++      dev_info(gf->dev, "Shutdown timeout: %d ms\n",
++               gf->shutdown_timeout_ms);
++
++      for (i = 0; i < gf->num_states; i++) {
++              struct fsm_state *state = &gf->states[i];
++
++              dev_info(gf->dev, "State %s:\n", state->name);
++
++              if (state->shutdown_target == state)
++                      dev_info(gf->dev, "  Shutdown state\n");
++
++              dev_info(gf->dev, "  Signals:\n");
++              for (j = 0; j < state->num_signals; j++) {
++                      struct output_signal *signal = &state->signals[j];
++
++                      dev_info(gf->dev, "    %d: %s %d=%d\n", j,
++                               (signal->type == SIGNAL_GPIO) ? "GPIO" :
++                                                               "SOFT",
++                               signal->index, signal->value);
++              }
++
++              dev_info(gf->dev, "  GPIO events:\n");
++              for (j = 0; j < state->num_gpio_events; j++) {
++                      struct gpio_event *event = &state->gpio_events[j];
++
++                      dev_info(gf->dev, "    %d: %d=%d -> %s\n", j,
++                               event->index, event->value,
++                               event->target->name);
++              }
++
++              dev_info(gf->dev, "  Soft events:\n");
++              for (j = 0; j < state->num_soft_events; j++) {
++                      struct gpio_event *event = &state->soft_events[j];
++
++                      dev_info(gf->dev, "    %d: %d=%d -> %s\n", j,
++                               event->index, event->value,
++                               event->target->name);
++              }
++
++              if (state->delay_target)
++                      dev_info(gf->dev, "  Delay: %d ms -> %s\n",
++                               state->delay_ms, state->delay_target->name);
++
++              if (state->shutdown_target && state->shutdown_target != state)
++                      dev_info(gf->dev, "  Shutdown: %d ms -> %s\n",
++                               state->shutdown_ms,
++                               state->shutdown_target->name);
++      }
++      dev_info(gf->dev, "\n");
++}
++
++static int resolve_sym_to_state(struct gpio_fsm *gf, struct fsm_state **pstate)
++{
++      struct symtab_entry *sym = (struct symtab_entry *)*pstate;
++
++      if (!sym)
++              return -ENOMEM;
++
++      *pstate = sym->value;
++
++      if (!*pstate) {
++              dev_err(gf->dev, "state %s not defined\n",
++                      sym->name);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int gpio_fsm_probe(struct platform_device *pdev)
++{
++      struct input_gpio_state *inp_state;
++      struct device *dev = &pdev->dev;
++      struct device_node *np = dev->of_node;
++      struct device_node *cp;
++      struct gpio_fsm *gf;
++      u32 debug = 0;
++      int num_states;
++      u32 num_soft_gpios;
++      int ret;
++      int i;
++      static const char *const reserved_symbols[] = {
++              [SYM_NAME] = "name",
++              [SYM_SET] = "set",
++              [SYM_START] = "start_state",
++              [SYM_SHUTDOWN] = "shutdown_state",
++      };
++
++      if (of_property_read_u32(np, "num-soft-gpios", &num_soft_gpios)) {
++              dev_err(dev, "missing 'num-soft-gpios' property\n");
++              return -EINVAL;
++      }
++
++      of_property_read_u32(np, "debug", &debug);
++
++      gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL);
++      if (!gf)
++              return -ENOMEM;
++
++      gf->dev = dev;
++      gf->debug = debug;
++
++      if (of_property_read_u32(np, "shutdown-timeout-ms",
++                               &gf->shutdown_timeout_ms))
++              gf->shutdown_timeout_ms = 5000;
++
++      gf->num_soft_gpios = num_soft_gpios;
++      gf->soft_gpios = devm_kcalloc(dev, num_soft_gpios,
++                                    sizeof(struct soft_gpio), GFP_KERNEL);
++      if (!gf->soft_gpios)
++              return -ENOMEM;
++      for (i = 0; i < num_soft_gpios; i++) {
++              struct soft_gpio *sg = &gf->soft_gpios[i];
++
++              sg->dir = GPIOF_DIR_IN;
++              sg->value = 0;
++      }
++
++      gf->input_gpios = devm_gpiod_get_array_optional(dev, "input", GPIOD_IN);
++      if (IS_ERR(gf->input_gpios)) {
++              ret = PTR_ERR(gf->input_gpios);
++              dev_err(dev, "failed to get input gpios from DT - %d\n", ret);
++              return ret;
++      }
++      gf->num_input_gpios = (gf->input_gpios ? gf->input_gpios->ndescs : 0);
++
++      gf->input_gpio_states = devm_kcalloc(dev, gf->num_input_gpios,
++                                           sizeof(struct input_gpio_state),
++                                           GFP_KERNEL);
++      if (!gf->input_gpio_states)
++              return -ENOMEM;
++      for (i = 0; i < gf->num_input_gpios; i++) {
++              inp_state = &gf->input_gpio_states[i];
++              inp_state->desc = gf->input_gpios->desc[i];
++              inp_state->gf = gf;
++              inp_state->index = i;
++              inp_state->irq = gpiod_to_irq(inp_state->desc);
++              inp_state->active_low = gpiod_is_active_low(inp_state->desc);
++              if (inp_state->irq >= 0)
++                      ret = devm_request_irq(gf->dev, inp_state->irq,
++                                             gpio_fsm_gpio_irq_handler,
++                                             IRQF_TRIGGER_NONE,
++                                             dev_name(dev),
++                                             inp_state);
++              else
++                      ret = inp_state->irq;
++
++              if (ret) {
++                      dev_err(dev,
++                              "failed to get IRQ for input gpio - %d\n",
++                              ret);
++                      return ret;
++              }
++      }
++
++      gf->output_gpios = devm_gpiod_get_array_optional(dev, "output",
++                                                       GPIOD_OUT_LOW);
++      if (IS_ERR(gf->output_gpios)) {
++              ret = PTR_ERR(gf->output_gpios);
++              dev_err(dev, "failed to get output gpios from DT - %d\n", ret);
++              return ret;
++      }
++      gf->num_output_gpios = (gf->output_gpios ? gf->output_gpios->ndescs :
++                              0);
++
++      num_states = of_get_child_count(np);
++      if (!num_states) {
++              dev_err(dev, "no states declared\n");
++              return -EINVAL;
++      }
++      gf->states = devm_kcalloc(dev, num_states,
++                                sizeof(struct fsm_state), GFP_KERNEL);
++      if (!gf->states)
++              return -ENOMEM;
++
++      // add reserved words to the symbol table
++      for (i = 0; i < ARRAY_SIZE(reserved_symbols); i++) {
++              if (reserved_symbols[i])
++                      add_symbol(&gf->symtab, reserved_symbols[i], (void *)i);
++      }
++
++      // parse the state
++      for_each_child_of_node(np, cp) {
++              struct fsm_state *state = &gf->states[gf->num_states];
++
++              ret = gpio_fsm_parse_state(gf, state, cp);
++              if (ret)
++                      return ret;
++              gf->num_states++;
++      }
++
++      if (!gf->start_state) {
++              dev_err(gf->dev, "no start state defined\n");
++              return -EINVAL;
++      }
++
++      // resolve symbol pointers into state pointers
++      for (i = 0; !ret && i < gf->num_states; i++) {
++              struct fsm_state *state = &gf->states[i];
++              int j;
++
++              for (j = 0; !ret && j < state->num_gpio_events; j++) {
++                      struct gpio_event *ev = &state->gpio_events[j];
++
++                      ret = resolve_sym_to_state(gf, &ev->target);
++              }
++
++              for (j = 0; !ret && j < state->num_soft_events; j++) {
++                      struct gpio_event *ev = &state->soft_events[j];
++
++                      ret = resolve_sym_to_state(gf, &ev->target);
++              }
++
++              if (!ret) {
++                      resolve_sym_to_state(gf, &state->delay_target);
++                      if (state->shutdown_target != state)
++                              resolve_sym_to_state(gf,
++                                                   &state->shutdown_target);
++              }
++      }
++
++      if (!ret && gf->debug > 1)
++              dump_all(gf);
++
++      free_symbols(&gf->symtab);
++
++      if (ret)
++              return ret;
++
++      gf->gc.parent = dev;
++      gf->gc.label = np->name;
++      gf->gc.owner = THIS_MODULE;
++      gf->gc.of_node = np;
++      gf->gc.base = -1;
++      gf->gc.ngpio = num_soft_gpios;
++
++      gf->gc.get_direction = gpio_fsm_get_direction;
++      gf->gc.direction_input = gpio_fsm_direction_input;
++      gf->gc.direction_output = gpio_fsm_direction_output;
++      gf->gc.get = gpio_fsm_get;
++      gf->gc.set = gpio_fsm_set;
++      gf->gc.can_sleep = true;
++      spin_lock_init(&gf->spinlock);
++      INIT_WORK(&gf->work, gpio_fsm_work);
++      timer_setup(&gf->timer, gpio_fsm_timer, 0);
++      init_waitqueue_head(&gf->shutdown_event);
++
++      platform_set_drvdata(pdev, gf);
++
++      if (gf->debug)
++              dev_info(gf->dev, "Start -> %s\n", gf->start_state->name);
++
++      gpio_fsm_go_to_state(gf, gf->start_state);
++
++      return devm_gpiochip_add_data(dev, &gf->gc, gf);
++}
++
++static int gpio_fsm_remove(struct platform_device *pdev)
++{
++      struct gpio_fsm *gf = platform_get_drvdata(pdev);
++      int i;
++
++      if (gf->shutdown_state) {
++              if (gf->debug)
++                      dev_info(gf->dev, "Shutting down...\n");
++
++              spin_lock(&gf->spinlock);
++              gf->shutting_down = true;
++              if (gf->current_state->shutdown_target &&
++                  gf->current_state->shutdown_target != gf->current_state) {
++                      gf->delay_target_state =
++                              gf->current_state->shutdown_target;
++                      mod_timer(&gf->timer, gf->shutdown_jiffies);
++              }
++              spin_unlock(&gf->spinlock);
++
++              wait_event_timeout(gf->shutdown_event,
++                                 gf->current_state->shutdown_target ==
++                                 gf->current_state,
++                                 msecs_to_jiffies(gf->shutdown_timeout_ms));
++              if (gf->current_state->shutdown_target == gf->current_state)
++                      gpio_fsm_enter_state(gf, gf->shutdown_state);
++      }
++      cancel_work_sync(&gf->work);
++      del_timer_sync(&gf->timer);
++
++      /* Events aren't allocated from managed storage */
++      for (i = 0; i < gf->num_states; i++) {
++              kfree(gf->states[i].gpio_events);
++              kfree(gf->states[i].soft_events);
++      }
++      if (gf->debug)
++              dev_info(gf->dev, "Exiting\n");
++
++      return 0;
++}
++
++static void gpio_fsm_shutdown(struct platform_device *pdev)
++{
++      gpio_fsm_remove(pdev);
++}
++
++static const struct of_device_id gpio_fsm_ids[] = {
++      { .compatible = "rpi,gpio-fsm" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, gpio_fsm_ids);
++
++static struct platform_driver gpio_fsm_driver = {
++      .driver = {
++              .name           = MODULE_NAME,
++              .of_match_table = of_match_ptr(gpio_fsm_ids),
++      },
++      .probe = gpio_fsm_probe,
++      .remove = gpio_fsm_remove,
++      .shutdown = gpio_fsm_shutdown,
++};
++module_platform_driver(gpio_fsm_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
++MODULE_DESCRIPTION("GPIO FSM driver");
++MODULE_ALIAS("platform:gpio-fsm");
+--- /dev/null
++++ b/include/dt-bindings/gpio/gpio-fsm.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * This header provides constants for binding rpi,gpio-fsm.
++ */
++
++#ifndef _DT_BINDINGS_GPIO_FSM_H
++#define _DT_BINDINGS_GPIO_FSM_H
++
++#define GF_IN       0
++#define GF_OUT      1
++#define GF_SOFT     2
++#define GF_DELAY    3
++#define GF_SHUTDOWN 4
++
++#define GF_IO(t, v) (((v) << 16) | ((t) & 0xffff))
++
++#define GF_IP(x)    GF_IO(GF_IN, (x))
++#define GF_OP(x)    GF_IO(GF_OUT, (x))
++#define GF_SW(x)    GF_IO(GF_SOFT, (x))
++
++#endif
diff --git a/target/linux/bcm27xx/patches-5.4/950-0987-overlays-Add-fsm-demo-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-0987-overlays-Add-fsm-demo-overlay.patch
new file mode 100644 (file)
index 0000000..7b56627
--- /dev/null
@@ -0,0 +1,151 @@
+From d27d1447e49bc6ffa92f787f7bc5c2eea29ba7d2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 30 Sep 2020 12:08:08 +0100
+Subject: [PATCH] overlays: Add fsm-demo overlay
+
+fsm-demo demonstrates the usage of the gpio-fsm driver. It is
+designed to be used with a set of "traffic light" LEDs on GPIOs
+7, 8 and 25.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   8 ++
+ .../boot/dts/overlays/fsm-demo-overlay.dts    | 104 ++++++++++++++++++
+ 3 files changed, 113 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/fsm-demo-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -44,6 +44,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       enc28j60-spi2.dtbo \
+       exc3000.dtbo \
+       fe-pi-audio.dtbo \
++      fsm-demo.dtbo \
+       goodix.dtbo \
+       googlevoicehat-soundcard.dtbo \
+       gpio-fan.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -767,6 +767,14 @@ Load:   dtoverlay=fe-pi-audio
+ Params: <None>
++Name:   fsm-demo
++Info:   A demonstration of the gpio-fsm driver. The GPIOs are chosen to work
++        nicely with a "traffic-light" display of red, amber and green LEDs on
++        GPIOs 7, 8 and 25 respectively.
++Load:   dtoverlay=fsm-demo,<param>=<val>
++Params: fsm_debug               Enable debug logging (default off)
++
++
+ Name:   goodix
+ Info:   Enables I2C connected Goodix gt9271 multiple touch controller using
+         GPIOs 4 and 17 (pins 7 and 11 on GPIO header) for interrupt and reset.
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/fsm-demo-overlay.dts
+@@ -0,0 +1,104 @@
++// Demo overlay for the gpio-fsm driver
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio-fsm.h>
++
++#define BUTTON1 GF_IP(0)
++#define BUTTON2 GF_SW(0)
++#define RED   GF_OP(0) // GPIO7
++#define AMBER GF_OP(1) // GPIO8
++#define GREEN GF_OP(2) // GPIO25
++
++/{
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target-path = "/";
++              __overlay__ {
++                      fsm_demo: fsm-demo {
++                              compatible = "rpi,gpio-fsm";
++
++                              debug = <0>;
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              num-soft-gpios = <1>;
++                              gpio-line-names = "button2";
++                              input-gpios  = <&gpio 6 1>;  // BUTTON1 (active-low)
++                              output-gpios = <&gpio 7 0>,  // RED
++                                             <&gpio 8 0>,  // AMBER
++                                             <&gpio 25 0>; // GREEN
++                              shutdown-timeout-ms = <2000>;
++
++                              start {
++                                      start_state;
++                                      set = <RED 1>, <AMBER 0>, <GREEN 0>;
++                                      start2 = <GF_DELAY 250>;
++                              };
++
++                              start2 {
++                                      set = <RED 0>, <AMBER 1>;
++                                      go = <GF_DELAY 250>;
++                              };
++
++                              go {
++                                      set = <RED 0>, <AMBER 0>, <GREEN 1>;
++                                      ready_wait = <BUTTON1 0>;
++                                      shutdown1 = <GF_SHUTDOWN 0>;
++                              };
++
++                              ready_wait {
++                                      // Clear the soft GPIO
++                                      set = <BUTTON2 0>;
++                                      ready = <GF_DELAY 1000>;
++                                      shutdown1 = <GF_SHUTDOWN 0>;
++                              };
++
++                              ready {
++                                      stopping = <BUTTON1 1>, <BUTTON2 1>;
++                                      shutdown1 = <GF_SHUTDOWN 0>;
++                              };
++
++                              stopping {
++                                      set = <GREEN 0>, <AMBER 1>;
++                                      stopped = <GF_DELAY 1000>;
++                              };
++
++                              stopped {
++                                      set = <AMBER 0>, <RED 1>;
++                                      get_set = <GF_DELAY 3000>;
++                                      shutdown1 = <GF_SHUTDOWN 0>;
++                              };
++
++                              get_set {
++                                      set = <AMBER 1>;
++                                      go = <GF_DELAY 1000>;
++                              };
++
++                              shutdown1 {
++                                      set = <RED 0>, <AMBER 0>, <GREEN 1>;
++                                      shutdown2 = <GF_SHUTDOWN 250>;
++                              };
++
++                              shutdown2 {
++                                      set = <AMBER 1>, <GREEN 0>;
++                                      shutdown3 = <GF_SHUTDOWN 250>;
++                              };
++
++                              shutdown3 {
++                                      set = <RED 1>, <AMBER 0>;
++                                      shutdown4 = <GF_SHUTDOWN 250>;
++                              };
++
++                              shutdown4 {
++                                      shutdown_state;
++                                      set = <RED 0>;
++                              };
++                      };
++             };
++        };
++
++      __overrides__ {
++              fsm_debug = <&fsm_demo>,"debug:0";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0988-overlays-Add-ghost-amp-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-0988-overlays-Add-ghost-amp-overlay.patch
new file mode 100644 (file)
index 0000000..7404bf7
--- /dev/null
@@ -0,0 +1,163 @@
+From 96f25d50e2352922e16ae74bb16fd8b6985f0f66 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 30 Sep 2020 12:17:48 +0100
+Subject: [PATCH] overlays: Add ghost-amp overlay
+
+Add an overlay for the Ghost amplifier.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   7 ++
+ .../boot/dts/overlays/ghost-amp-overlay.dts   | 119 ++++++++++++++++++
+ 3 files changed, 127 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/ghost-amp-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -45,6 +45,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       exc3000.dtbo \
+       fe-pi-audio.dtbo \
+       fsm-demo.dtbo \
++      ghost-amp.dtbo \
+       goodix.dtbo \
+       googlevoicehat-soundcard.dtbo \
+       gpio-fan.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -775,6 +775,13 @@ Load:   dtoverlay=fsm-demo,<param>=<val>
+ Params: fsm_debug               Enable debug logging (default off)
++Name:   ghost-amp
++Info:   An overlay for the Ghost amplifier.
++Load:   dtoverlay=ghost-amp,<param>=<val>
++Params: fsm_debug               Enable debug logging of the GPIO FSM (default
++                                off)
++
++
+ Name:   goodix
+ Info:   Enables I2C connected Goodix gt9271 multiple touch controller using
+         GPIOs 4 and 17 (pins 7 and 11 on GPIO header) for interrupt and reset.
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/ghost-amp-overlay.dts
+@@ -0,0 +1,119 @@
++// Overlay for the PCM5122-based Ghost amplifier using gpio-fsm
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio-fsm.h>
++
++#define ENABLE GF_SW(0)
++#define FAULT  GF_IP(0) // GPIO5
++#define RELAY1 GF_OP(0) // GPIO22
++#define RELAY2 GF_OP(1) // GPIO23
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pcm5122@4c {
++                              #sound-dai-cells = <0>;
++                              compatible = "ti,pcm5122";
++                              reg = <0x4c>;
++                              AVDD-supply = <&vdd_3v3_reg>;
++                              DVDD-supply = <&vdd_3v3_reg>;
++                              CPVDD-supply = <&vdd_3v3_reg>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&sound>;
++              iqaudio_dac: __overlay__ {
++                      compatible = "iqaudio,iqaudio-dac";
++                      i2s-controller = <&i2s>;
++                      mute-gpios = <&amp 0 0>;
++                      iqaudio-dac,auto-mute-amp;
++                      status = "okay";
++              };
++      };
++
++      fragment@3 {
++              target-path = "/";
++              __overlay__ {
++                      amp: ghost-amp {
++                              compatible = "rpi,gpio-fsm";
++
++                              debug = <0>;
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              num-soft-gpios = <1>;
++                              gpio-line-names = "enable";
++                              input-gpios  = <&gpio 5 1>;  // FAULT (active low)
++                              output-gpios = <&gpio 22 0>, // RELAY1
++                                             <&gpio 23 0>; // RELAY2
++                              shutdown-timeout-ms = <1000>;
++
++                              amp_off {
++                                      start_state;
++                                      shutdown_state;
++
++                                      set = <RELAY2 0>,
++                                            <RELAY1 0>;
++                                      amp_on_1 = <ENABLE 1>;
++                                      fault = <FAULT 1>;
++                              };
++
++                              amp_on_1 {
++                                      set = <RELAY1 1>;
++                                      amp_on = <GF_DELAY 1500>;
++                                      amp_off = <ENABLE 0>;
++                                      fault = <FAULT 1>;
++                              };
++
++                              amp_on {
++                                      set = <RELAY2 1>;
++                                      amp_off_wait = <ENABLE 0>;
++                                      fault = <FAULT 1>;
++                              };
++
++                              amp_off_wait {
++                                      amp_off_1 = <GF_DELAY (30*60*1000)>,
++                                                  <GF_SHUTDOWN 0>;
++                                      amp_on = <ENABLE 1>;
++                                      fault = <FAULT 1>;
++                              };
++
++                              amp_off_1 {
++                                      set = <RELAY2 0>;
++                                      amp_on = <ENABLE 1>;
++                                      amp_off = <GF_DELAY 100>;
++                                      fault = <FAULT 1>;
++                              };
++
++                              // Keep this a distinct state to prevent
++                              // changes and for the diagnostic output
++                              fault {
++                                      set = <RELAY2 0>,
++                                            <RELAY1 0>;
++                                      shutdown_state;
++                              };
++                      };
++              };
++      };
++
++      __overrides__ {
++              fsm_debug = <&amp>,"debug:0";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-0989-Bluetooth-Disable-High-Speed-by-default.patch b/target/linux/bcm27xx/patches-5.4/950-0989-Bluetooth-Disable-High-Speed-by-default.patch
new file mode 100644 (file)
index 0000000..0317312
--- /dev/null
@@ -0,0 +1,26 @@
+From 8ccf890b3514c07c0596a8a3e389e08fd00c0d8e Mon Sep 17 00:00:00 2001
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Date: Thu, 6 Aug 2020 11:17:13 -0700
+Subject: [PATCH] Bluetooth: Disable High Speed by default
+
+commit b176dd0ef6afcb3bca24f41d78b0d0b731ec2d08 upstream.
+
+Bluetooth High Speed requires hardware support which is very uncommon
+nowadays since HS has not pickup interest by the industry.
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+ net/bluetooth/Kconfig | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/net/bluetooth/Kconfig
++++ b/net/bluetooth/Kconfig
+@@ -64,7 +64,6 @@ source "net/bluetooth/hidp/Kconfig"
+ config BT_HS
+       bool "Bluetooth High Speed (HS) features"
+       depends on BT_BREDR
+-      default y
+       help
+         Bluetooth High Speed includes support for off-loading
+         Bluetooth connections via 802.11 (wifi) physical layer
diff --git a/target/linux/bcm27xx/patches-5.4/950-0990-Fixes-a-problem-when-module-probes-before-i2c-module.patch b/target/linux/bcm27xx/patches-5.4/950-0990-Fixes-a-problem-when-module-probes-before-i2c-module.patch
new file mode 100644 (file)
index 0000000..e939772
--- /dev/null
@@ -0,0 +1,46 @@
+From bc55eb17b46668e70dfbd1a091159935d8f95eb9 Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joerg@i2audio.com>
+Date: Fri, 16 Oct 2020 15:17:07 +0200
+Subject: [PATCH] Fixes a problem when module probes before i2c
+ module is available
+
+The driver crashed while a NULL pointer returned by i2c_get_adapter()
+has been used to access the i2c bus functions.
+The headphone probing function hb_hp_probe() now returns -EPROBE_DEFER
+in case the i2c module has not been loaded yet.
+
+Signed-off-by: Joerg Schambacher <joerg@i2audio.com>
+---
+ sound/soc/bcm/hifiberry_dacplus.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/bcm/hifiberry_dacplus.c
++++ b/sound/soc/bcm/hifiberry_dacplus.c
+@@ -315,12 +315,14 @@ static int hb_hp_detect(void)
+ {
+       struct i2c_adapter *adap = i2c_get_adapter(1);
+       int ret;
+-
+       struct i2c_client tpa_i2c_client = {
+               .addr = 0x60,
+               .adapter = adap,
+       };
++      if (!adap)
++              return -EPROBE_DEFER;   /* I2C module not yet available */
++
+       ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
+       i2c_put_adapter(adap);
+       return ret;
+@@ -342,7 +344,10 @@ static int snd_rpi_hifiberry_dacplus_pro
+       struct of_changeset ocs;
+       /* probe for head phone amp */
+-      if (hb_hp_detect()) {
++      ret = hb_hp_detect();
++      if (ret < 0)
++              return ret;
++      if (ret) {
+               card->aux_dev = hifiberry_dacplus_aux_devs;
+               card->num_aux_devs =
+                               ARRAY_SIZE(hifiberry_dacplus_aux_devs);
diff --git a/target/linux/bcm27xx/patches-5.4/950-0991-uapi-Update-V4L2_CID_USER_BCM2835_ISP_BASE-due-to-up.patch b/target/linux/bcm27xx/patches-5.4/950-0991-uapi-Update-V4L2_CID_USER_BCM2835_ISP_BASE-due-to-up.patch
new file mode 100644 (file)
index 0000000..71c27e1
--- /dev/null
@@ -0,0 +1,41 @@
+From 90e833fddb15bbdd8aeb6285ba596b4c657383c2 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 15 Oct 2020 11:59:02 +0100
+Subject: [PATCH] uapi: Update V4L2_CID_USER_BCM2835_ISP_BASE due to
+ upstream change
+
+Commit "4e52889 media: atmel: atmel-isc-base: expose white
+balance as v4l2 controls" in the upstream kernels reserves
+(V4L2_CID_USER_BASE + 0x10c0) for use by the Atmel ISC,
+therefore we have a control collision with our existing
+define for V4L2_CID_USER_BCM2835_ISP_BASE.
+
+Update V4L2_CID_USER_BCM2835_ISP_BASE to + 0x10e0 as the
+next available block.
+
+NB ABI breakage for libcamera (the only user of these controls).
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ include/uapi/linux/v4l2-controls.h | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/include/uapi/linux/v4l2-controls.h
++++ b/include/uapi/linux/v4l2-controls.h
+@@ -192,9 +192,15 @@ enum v4l2_colorfx {
+  * We reserve 16 controls for this driver. */
+ #define V4L2_CID_USER_IMX_BASE                        (V4L2_CID_USER_BASE + 0x10b0)
++/*
++ * The base for the atmel isc driver controls.
++ * We reserve 32 controls for this driver.
++ */
++#define V4L2_CID_USER_ATMEL_ISC_BASE          (V4L2_CID_USER_BASE + 0x10c0)
++
+ /* The base for the bcm2835-isp driver controls.
+  * We reserve 16 controls for this driver. */
+-#define V4L2_CID_USER_BCM2835_ISP_BASE                (V4L2_CID_USER_BASE + 0x10c0)
++#define V4L2_CID_USER_BCM2835_ISP_BASE                (V4L2_CID_USER_BASE + 0x10e0)
+ /* MPEG-class control IDs */
+ /* The MPEG controls are applicable to all codec controls
diff --git a/target/linux/bcm27xx/patches-5.4/950-0992-dtoverlays-Correct-CSI2-settings-for-ov9281.patch b/target/linux/bcm27xx/patches-5.4/950-0992-dtoverlays-Correct-CSI2-settings-for-ov9281.patch
new file mode 100644 (file)
index 0000000..84a4e98
--- /dev/null
@@ -0,0 +1,36 @@
+From ac315f66be96c5a423382efb559f193e5b786226 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 21 Oct 2020 18:33:02 +0100
+Subject: [PATCH] dtoverlays: Correct CSI2 settings for ov9281
+
+OV9281 appears to drop the clock to LP mode between frames, but
+the overlay didn't define this at both ends of the CSI2 link.
+The overlay also had an incorrect link frequency defined, not that
+the driver ever checked for one.
+
+Fix both issues.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/ov9281-overlay.dts | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/overlays/ov9281-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts
+@@ -34,7 +34,7 @@
+                                               data-lanes = <1 2>;
+                                               clock-noncontinuous;
+                                               link-frequencies =
+-                                                      /bits/ 64 <456000000>;
++                                                      /bits/ 64 <400000000>;
+                                       };
+                               };
+                       };
+@@ -50,6 +50,7 @@
+                               csi1_ep: endpoint {
+                                       remote-endpoint = <&ov9281_0>;
+                                       data-lanes = <1 2>;
++                                      clock-noncontinuous;
+                               };
+                       };
+               };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0993-xhci-quirks-add-link-TRB-quirk-for-VL805.patch b/target/linux/bcm27xx/patches-5.4/950-0993-xhci-quirks-add-link-TRB-quirk-for-VL805.patch
new file mode 100644 (file)
index 0000000..3c89f13
--- /dev/null
@@ -0,0 +1,61 @@
+From 510fccc1a7533aa9f46d97ad500fe45ab7f91010 Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Mon, 26 Oct 2020 14:03:35 +0000
+Subject: [PATCH] xhci: quirks: add link TRB quirk for VL805
+
+The VL805 controller can't cope with the TR Dequeue Pointer for an endpoint
+being set to a Link TRB. The hardware-maintained endpoint context ends up
+stuck at the address of the Link TRB, leading to erroneous ring expansion
+events whenever the enqueue pointer wraps to the dequeue position.
+
+If the search for the end of the current TD and ring cycle state lands on
+a Link TRB, move to the next segment.
+
+See: https://github.com/raspberrypi/linux/issues/3919
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
+---
+ drivers/usb/host/xhci-pci.c  |  1 +
+ drivers/usb/host/xhci-ring.c | 10 ++++++++++
+ drivers/usb/host/xhci.h      |  1 +
+ 3 files changed, 12 insertions(+)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -258,6 +258,7 @@ static void xhci_pci_quirks(struct devic
+                       pdev->device == 0x3483) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
++              xhci->quirks |= XHCI_AVOID_DQ_ON_LINK;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -624,6 +624,16 @@ void xhci_find_new_dequeue_state(struct
+       } while (!cycle_found || !td_last_trb_found);
++      /*
++       * Quirk: the xHC does not correctly parse link TRBs if the HW Dequeue
++       * pointer is set to one. Advance to the next TRB (and next segment).
++       */
++      if (xhci->quirks & XHCI_AVOID_DQ_ON_LINK && trb_is_link(new_deq)) {
++              if (link_trb_toggles_cycle(new_deq))
++                      state->new_cycle_state ^= 0x1;
++              next_trb(xhci, ep_ring, &new_seg, &new_deq);
++      }
++
+       state->new_deq_seg = new_seg;
+       state->new_deq_ptr = new_deq;
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1876,6 +1876,7 @@ struct xhci_hcd {
+ #define XHCI_EP_CTX_BROKEN_DCS        BIT_ULL(36)
+ #define XHCI_SKIP_PHY_INIT    BIT_ULL(37)
+ #define XHCI_DISABLE_SPARSE   BIT_ULL(38)
++#define XHCI_AVOID_DQ_ON_LINK BIT_ULL(39)
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0994-dts-Add-CM4-to-arm64-dt-files.patch b/target/linux/bcm27xx/patches-5.4/950-0994-dts-Add-CM4-to-arm64-dt-files.patch
new file mode 100644 (file)
index 0000000..03d0fe8
--- /dev/null
@@ -0,0 +1,28 @@
+From 0ea39ee546de55f9dcf5729f1e39ebc2747477ba Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Fri, 23 Oct 2020 15:45:11 +0100
+Subject: [PATCH] dts: Add CM4 to arm64 dt files
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ arch/arm64/boot/dts/broadcom/Makefile            | 3 ++-
+ arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4.dts | 1 +
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4.dts
+
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -7,7 +7,8 @@ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rp
+ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-2-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
+-dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb
++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb \
++                            bcm2711-rpi-cm4.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4.dts
+@@ -0,0 +1 @@
++#include "../../../../arm/boot/dts/bcm2711-rpi-cm4.dts"
diff --git a/target/linux/bcm27xx/patches-5.4/950-0995-dts-Tidy-the-Raspberry-Pi-Makefile-entries.patch b/target/linux/bcm27xx/patches-5.4/950-0995-dts-Tidy-the-Raspberry-Pi-Makefile-entries.patch
new file mode 100644 (file)
index 0000000..af427f4
--- /dev/null
@@ -0,0 +1,43 @@
+From fd3620d39c813e9846ace3511bc96a868b5be61a Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 26 Oct 2020 15:01:21 +0000
+Subject: [PATCH] dts: Tidy the Raspberry Pi Makefile entries
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/Makefile            | 2 +-
+ arch/arm64/boot/dts/broadcom/Makefile | 7 ++-----
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -10,8 +10,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2709-rpi-2-b.dtb \
+       bcm2710-rpi-2-b.dtb \
+       bcm2710-rpi-3-b.dtb \
+-      bcm2711-rpi-4-b.dtb \
+       bcm2710-rpi-3-b-plus.dtb \
++      bcm2711-rpi-4-b.dtb \
+       bcm2710-rpi-cm3.dtb \
+       bcm2711-rpi-cm4.dtb
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -3,15 +3,12 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rp
+                             bcm2837-rpi-3-b.dtb \
+                             bcm2837-rpi-3-b-plus.dtb \
+                             bcm2837-rpi-cm3-io3.dtb
+-dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-2-b.dtb
+-dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-2-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
+-dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb \
+-                            bcm2711-rpi-cm4.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
+-dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-cm3.dtb
++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb
++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4.dtb
+ subdir-y      += northstar2
+ subdir-y      += stingray
diff --git a/target/linux/bcm27xx/patches-5.4/950-0996-staging-bcm2835-audio-Add-disable-headphones-flag.patch b/target/linux/bcm27xx/patches-5.4/950-0996-staging-bcm2835-audio-Add-disable-headphones-flag.patch
new file mode 100644 (file)
index 0000000..3c30745
--- /dev/null
@@ -0,0 +1,34 @@
+From af217539bab20a3bba6e1bbd4e4c8f68e7644e50 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 26 Oct 2020 10:23:22 +0000
+Subject: [PATCH] staging: bcm2835-audio: Add disable-headphones flag
+
+Add a property to allow the headphone output to be disabled. Use an
+integer property rather than a boolean so that an overlay can clear it.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+@@ -381,11 +381,16 @@ static int snd_bcm2835_alsa_probe(struct
+       }
+       if (!enable_compat_alsa) {
++              // In this mode, enable analog output by default
++              u32 disable_headphones = 0;
++
+               if (!of_property_read_bool(dev->of_node, "brcm,disable-hdmi"))
+                       set_hdmi_enables(dev);
+-              // In this mode, always enable analog output
+-              enable_headphones = true;
++              of_property_read_u32(dev->of_node,
++                                   "brcm,disable-headphones",
++                                   &disable_headphones);
++              enable_headphones = !disable_headphones;
+       } else {
+               enable_hdmi0 = enable_hdmi;
+       }
diff --git a/target/linux/bcm27xx/patches-5.4/950-0997-ARM-dts-Disable-headphone-audio-on-Zeroes-CM4.patch b/target/linux/bcm27xx/patches-5.4/950-0997-ARM-dts-Disable-headphone-audio-on-Zeroes-CM4.patch
new file mode 100644 (file)
index 0000000..475d0a8
--- /dev/null
@@ -0,0 +1,42 @@
+From 9fc10178e1130b43ccc8b855a73fb22643963da0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 26 Oct 2020 10:18:50 +0000
+Subject: [PATCH] ARM: dts: Disable headphone audio on Zeroes, CM4
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 1 +
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts   | 1 +
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts    | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -152,6 +152,7 @@
+ &audio {
+       pinctrl-names = "default";
+       pinctrl-0 = <&audio_pins>;
++      brcm,disable-headphones = <1>;
+ };
+ / {
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -106,6 +106,7 @@
+ &audio {
+       pinctrl-names = "default";
+       pinctrl-0 = <&audio_pins>;
++      brcm,disable-headphones = <1>;
+ };
+ / {
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -460,6 +460,7 @@
+ &audio {
+       pinctrl-names = "default";
+       pinctrl-0 = <&audio_pins>;
++      brcm,disable-headphones = <1>;
+ };
+ &vc4 {
diff --git a/target/linux/bcm27xx/patches-5.4/950-0998-overlays-Enable-headphone-audio-in-audremap.patch b/target/linux/bcm27xx/patches-5.4/950-0998-overlays-Enable-headphone-audio-in-audremap.patch
new file mode 100644 (file)
index 0000000..e206ca4
--- /dev/null
@@ -0,0 +1,26 @@
+From 4a69ef912ed791855fcc058230eed14342c6cd02 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 26 Oct 2020 10:21:23 +0000
+Subject: [PATCH] overlays: Enable headphone audio in audremap
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/audremap-overlay.dts | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/audremap-overlay.dts
++++ b/arch/arm/boot/dts/overlays/audremap-overlay.dts
+@@ -26,6 +26,13 @@
+               };
+       };
++      fragment@3 {
++              target = <&audio>;
++              __overlay__  {
++                      brcm,disable-headphones = <0>;
++              };
++      };
++
+       __overrides__ {
+               swap_lr = <&frag0>, "swap_lr?";
+               enable_jack = <&frag0>, "enable_jack?";
diff --git a/target/linux/bcm27xx/patches-5.4/950-0999-rpisense-fb-Set-pseudo_pallete-to-prevent-crash-on-f.patch b/target/linux/bcm27xx/patches-5.4/950-0999-rpisense-fb-Set-pseudo_pallete-to-prevent-crash-on-f.patch
new file mode 100644 (file)
index 0000000..66d9c69
--- /dev/null
@@ -0,0 +1,30 @@
+From 24a2cc7c39f7232b5256dc8adb2f2e87ee1062ec Mon Sep 17 00:00:00 2001
+From: Serge Schneider <serge@raspberrypi.com>
+Date: Mon, 26 Oct 2020 16:38:21 +0000
+Subject: [PATCH] rpisense-fb: Set pseudo_pallete to prevent crash on
+ fbcon takeover
+
+Signed-off-by: Serge Schneider <serge@raspberrypi.com>
+---
+ drivers/video/fbdev/rpisense-fb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/video/fbdev/rpisense-fb.c
++++ b/drivers/video/fbdev/rpisense-fb.c
+@@ -52,6 +52,8 @@ static u8 gamma_low[32] = {0x00, 0x01, 0
+ static u8 gamma_user[32];
++static u32 pseudo_palette[16];
++
+ static struct rpisense_fb_param rpisense_fb_param = {
+       .vmem = NULL,
+       .vmemsize = 128,
+@@ -225,6 +227,7 @@ static int rpisense_fb_probe(struct plat
+       info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+       info->screen_base = rpisense_fb_param.vmem;
+       info->screen_size = rpisense_fb_param.vmemsize;
++      info->pseudo_palette = pseudo_palette;
+       if (lowlight)
+               rpisense_fb_param.gamma = gamma_low;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1000-PiFi-40-Devicetree-files.patch b/target/linux/bcm27xx/patches-5.4/950-1000-PiFi-40-Devicetree-files.patch
new file mode 100644 (file)
index 0000000..06f5da6
--- /dev/null
@@ -0,0 +1,91 @@
+From a822d6667a687451cdf65aef66ecc7fa15891205 Mon Sep 17 00:00:00 2001
+From: David Knell <david.knell@gmail.com>
+Date: Wed, 28 Oct 2020 14:20:56 +0000
+Subject: [PATCH] PiFi-40 Devicetree files
+
+Signed-off-by: David Knell <david.knell@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  6 +++
+ .../arm/boot/dts/overlays/pifi-40-overlay.dts | 50 +++++++++++++++++++
+ 3 files changed, 57 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/pifi-40-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -125,6 +125,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       pca953x.dtbo \
+       pibell.dtbo \
+       pifacedigital.dtbo \
++      pifi-40.dtbo \
+       piglow.dtbo \
+       piscreen.dtbo \
+       piscreen2r.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2000,6 +2000,12 @@ Params: spi-present-mask        8-bit in
+                                 0-3, which can be configured with JP1 and JP2.
++Name:   pifi-40
++Info:   Configures the PiFi 40W stereo amplifier
++Load:   dtoverlay=pifi-40
++Params: <None>
++
++
+ Name:   piglow
+ Info:   Configures the PiGlow by pimoroni.com
+ Load:   dtoverlay=piglow
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/pifi-40-overlay.dts
+@@ -0,0 +1,50 @@
++// Definitions for PiFi-40 Amp
++/dts-v1/;
++/plugin/;
++#include <dt-bindings/gpio/gpio.h>
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      tas5711l: audio-codec@1a {
++                              compatible = "ti,tas5711";
++                              reg = <0x1a>;
++                              #sound-dai-cells = <0>;
++                              sound-name-prefix = "Left";
++                              status = "okay";
++                      };
++
++                      tas5711r: audio-codec@1b {
++                              compatible = "ti,tas5711";
++                              reg = <0x1b>;
++                              #sound-dai-cells = <0>;
++                              sound-name-prefix = "Right";
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&sound>;
++              pifi_40: __overlay__ {
++                      compatible = "pifi,pifi-40";
++                      audio-codec = <&tas5711l &tas5711r>;
++                      i2s-controller = <&i2s>;
++                      pdn-gpios = <&gpio 23 1>;
++                      status = "okay";
++              };
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1001-PiFi-40-driver-Makefile-and-Kconfig.patch b/target/linux/bcm27xx/patches-5.4/950-1001-PiFi-40-driver-Makefile-and-Kconfig.patch
new file mode 100644 (file)
index 0000000..5c584f4
--- /dev/null
@@ -0,0 +1,331 @@
+From b7bbdd72e5c9e1b7538b74deb584a7ab0f85847d Mon Sep 17 00:00:00 2001
+From: David Knell <david.knell@gmail.com>
+Date: Wed, 28 Oct 2020 14:21:37 +0000
+Subject: [PATCH] PiFi-40 driver, Makefile and Kconfig
+
+Signed-off-by: David Knell <david.knell@gmail.com>
+---
+ sound/soc/bcm/Kconfig   |   8 ++
+ sound/soc/bcm/Makefile  |   3 +
+ sound/soc/bcm/pifi-40.c | 282 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 293 insertions(+)
+ create mode 100644 sound/soc/bcm/pifi-40.c
+
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -91,6 +91,14 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP
+         help
+          Say Y or M if you want to add support for the HifiBerry Amp amplifier board.
++ config SND_BCM2708_SOC_PIFI_40
++         tristate "Support for the PiFi-40 amp"
++         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++         select SND_SOC_TAS571X
++         select SND_PIFI_40
++         help
++          Say Y or M if you want to add support for the PiFi40 amp board
++
+ config SND_BCM2708_SOC_RPI_CIRRUS
+         tristate "Support for Cirrus Logic Audio Card"
+         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -40,6 +40,7 @@ snd-soc-pisound-objs := pisound.o
+ snd-soc-fe-pi-audio-objs := fe-pi-audio.o
+ snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
+ snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
++snd-soc-pifi-40-objs := pifi-40.o
+ obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD)  += snd-soc-googlevoicehat-codec.o
+ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
+@@ -69,3 +70,5 @@ obj-$(CONFIG_SND_PISOUND) += snd-soc-pis
+ obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o
+ obj-$(CONFIG_SND_RPI_SIMPLE_SOUNDCARD) += snd-soc-rpi-simple-soundcard.o
+ obj-$(CONFIG_SND_RPI_WM8804_SOUNDCARD) += snd-soc-rpi-wm8804-soundcard.o
++obj-$(CONFIG_SND_BCM2708_SOC_PIFI_40) += snd-soc-pifi-40.o
++
+--- /dev/null
++++ b/sound/soc/bcm/pifi-40.c
+@@ -0,0 +1,282 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * ALSA ASoC Machine Driver for PiFi-40
++ *
++ * Author:    David Knell <david.knell@gmail.com)
++ *            based on code by Daniel Matuschek <info@crazy-audio.com>
++ *            based on code by Florian Meier <florian.meier@koalo.de>
++ * Copyright (C) 2020
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/gpio/consumer.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <linux/firmware.h>
++#include <linux/delay.h>
++#include <sound/tlv.h>
++
++static struct gpio_desc *pdn_gpio;
++static int vol = 0x30;
++
++// Volume control
++static int pifi_40_vol_get(struct snd_kcontrol *kcontrol,
++                         struct snd_ctl_elem_value *ucontrol)
++{
++      ucontrol->value.integer.value[0] = vol;
++      ucontrol->value.integer.value[1] = vol;
++      return 0;
++}
++
++static int pifi_40_vol_set(struct snd_kcontrol *kcontrol,
++                         struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
++      struct snd_soc_pcm_runtime *rtd;
++      unsigned int v = ucontrol->value.integer.value[0];
++      struct snd_soc_component *dac[2];
++
++      rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
++      dac[0] = rtd->codec_dais[0]->component;
++      dac[1] = rtd->codec_dais[1]->component;
++
++      snd_soc_component_write(dac[0], 0x07, 255 - v);
++      snd_soc_component_write(dac[1], 0x07, 255 - v);
++
++      vol = v;
++      return 1;
++}
++
++static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
++static const struct snd_kcontrol_new pifi_40_controls[] = {
++      SOC_DOUBLE_R_EXT_TLV("Master Volume", 0x00, 0x01,
++                           0x00, // Min
++                           0xff, // Max
++                           0x01, // Invert
++                           pifi_40_vol_get, pifi_40_vol_set,
++                           digital_tlv_master)
++};
++
++static const char * const codec_ctl_pfx[] = { "Left", "Right" };
++
++static const char * const codec_ctl_name[] = { "Master Volume",
++                                      "Speaker Volume",
++                                      "Speaker Switch" };
++
++static int snd_pifi_40_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct snd_soc_card *card = rtd->card;
++      struct snd_soc_component *dac[2];
++      struct snd_kcontrol *kctl;
++      int i, j;
++
++      dac[0] = rtd->codec_dais[0]->component;
++      dac[1] = rtd->codec_dais[1]->component;
++
++      // Set up cards - pulse power down first
++      gpiod_set_value_cansleep(pdn_gpio, 1);
++      usleep_range(1000, 10000);
++      gpiod_set_value_cansleep(pdn_gpio, 0);
++      usleep_range(20000, 30000);
++
++      // Oscillator trim
++      snd_soc_component_write(dac[0], 0x1b, 0);
++      snd_soc_component_write(dac[1], 0x1b, 0);
++      usleep_range(60000, 80000);
++
++      // Common setup
++      for (i = 0; i < 2; i++) {
++              // MCLK at 64fs, sample rate 44.1 or 48kHz
++              snd_soc_component_write(dac[i], 0x00, 0x60);
++
++              // Set up for PBTL
++              snd_soc_component_write(dac[i], 0x19, 0x3A);
++              snd_soc_component_write(dac[i], 0x25, 0x01103245);
++
++              // Master vol to -10db
++              snd_soc_component_write(dac[i], 0x07, 0x44);
++      }
++      // Inputs set to L and R respectively
++      snd_soc_component_write(dac[0], 0x20, 0x00017772);
++      snd_soc_component_write(dac[1], 0x20, 0x00107772);
++
++      // Remove codec controls
++      for (i = 0; i < 2; i++) {
++              for (j = 0; j < 3; j++) {
++                      char cname[256];
++
++                      sprintf(cname, "%s %s", codec_ctl_pfx[i],
++                              codec_ctl_name[j]);
++                      kctl = snd_soc_card_get_kcontrol(card, cname);
++                      if (!kctl) {
++                              pr_info("Control %s not found\n",
++                                     cname);
++                      } else {
++                              kctl->vd[0].access =
++                                      SNDRV_CTL_ELEM_ACCESS_READWRITE;
++                              snd_ctl_remove(card->snd_card, kctl);
++                      }
++              }
++      }
++
++      return 0;
++}
++
++static int snd_pifi_40_hw_params(struct snd_pcm_substream *substream,
++                               struct snd_pcm_hw_params *params)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++      unsigned int sample_bits;
++
++      sample_bits = snd_pcm_format_physical_width(params_format(params));
++      return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
++}
++
++static struct snd_soc_ops snd_pifi_40_ops = { .hw_params =
++                                                    snd_pifi_40_hw_params };
++
++static struct snd_soc_dai_link_component pifi_40_codecs[] = {
++      {
++              .dai_name = "tas571x-hifi",
++      },
++      {
++              .dai_name = "tas571x-hifi",
++      },
++};
++
++SND_SOC_DAILINK_DEFS(
++      pifi_40_dai, DAILINK_COMP_ARRAY(COMP_EMPTY()),
++      DAILINK_COMP_ARRAY(COMP_CODEC("tas571x.1-001a", "tas571x-hifi"),
++                         COMP_CODEC("tas571x.1-001b", "tas571x-hifi")),
++      DAILINK_COMP_ARRAY(COMP_EMPTY()));
++
++static struct snd_soc_dai_link snd_pifi_40_dai[] = {
++      {
++              .name = "PiFi40",
++              .stream_name = "PiFi40",
++              .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++                         SND_SOC_DAIFMT_CBS_CFS,
++              .ops = &snd_pifi_40_ops,
++              .init = snd_pifi_40_init,
++              SND_SOC_DAILINK_REG(pifi_40_dai),
++      },
++};
++
++// Machine driver
++static struct snd_soc_card snd_pifi_40 = {
++      .name = "PiFi40",
++      .owner = THIS_MODULE,
++      .dai_link = snd_pifi_40_dai,
++      .num_links = ARRAY_SIZE(snd_pifi_40_dai),
++      .controls = pifi_40_controls,
++      .num_controls = ARRAY_SIZE(pifi_40_controls)
++};
++
++static void snd_pifi_40_pdn(struct snd_soc_card *card, int on)
++{
++      if (pdn_gpio)
++              gpiod_set_value_cansleep(pdn_gpio, on ? 0 : 1);
++}
++
++static int snd_pifi_40_probe(struct platform_device *pdev)
++{
++      struct snd_soc_card *card = &snd_pifi_40;
++      int ret = 0, i = 0;
++
++      card->dev = &pdev->dev;
++      platform_set_drvdata(pdev, &snd_pifi_40);
++
++      if (pdev->dev.of_node) {
++              struct device_node *i2s_node;
++              struct snd_soc_dai_link *dai;
++
++              dai = &snd_pifi_40_dai[0];
++              i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller",
++                                          0);
++              if (i2s_node) {
++                      for (i = 0; i < card->num_links; i++) {
++                              dai->cpus->dai_name = NULL;
++                              dai->cpus->of_node = i2s_node;
++                              dai->platforms->name = NULL;
++                              dai->platforms->of_node = i2s_node;
++                      }
++              }
++
++              pifi_40_codecs[0].of_node =
++                      of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
++              pifi_40_codecs[1].of_node =
++                      of_parse_phandle(pdev->dev.of_node, "audio-codec", 1);
++              if (!pifi_40_codecs[0].of_node || !pifi_40_codecs[1].of_node) {
++                      dev_err(&pdev->dev,
++                              "Property 'audio-codec' missing or invalid\n");
++                      return -EINVAL;
++              }
++
++              pdn_gpio = devm_gpiod_get_optional(&pdev->dev, "pdn",
++                                                 GPIOD_OUT_LOW);
++              if (IS_ERR(pdn_gpio)) {
++                      ret = PTR_ERR(pdn_gpio);
++                      dev_err(&pdev->dev, "failed to get pdn gpio: %d\n",
++                              ret);
++                      return ret;
++              }
++
++              ret = snd_soc_register_card(&snd_pifi_40);
++              if (ret < 0) {
++                      dev_err(&pdev->dev,
++                              "snd_soc_register_card() failed: %d\n", ret);
++                      return ret;
++              }
++
++              return 0;
++      }
++
++      return -EINVAL;
++}
++
++static int snd_pifi_40_remove(struct platform_device *pdev)
++{
++      struct snd_soc_card *card = platform_get_drvdata(pdev);
++
++      kfree(&card->drvdata);
++      snd_pifi_40_pdn(&snd_pifi_40, 0);
++      return snd_soc_unregister_card(&snd_pifi_40);
++}
++
++static const struct of_device_id snd_pifi_40_of_match[] = {
++      {
++              .compatible = "pifi,pifi-40",
++      },
++      { /* sentinel */ },
++};
++
++MODULE_DEVICE_TABLE(of, snd_pifi_40_of_match);
++
++static struct platform_driver snd_pifi_40_driver = {
++      .driver = {
++              .name = "snd-pifi-40",
++              .owner = THIS_MODULE,
++              .of_match_table = snd_pifi_40_of_match,
++      },
++      .probe = snd_pifi_40_probe,
++      .remove = snd_pifi_40_remove,
++};
++
++module_platform_driver(snd_pifi_40_driver);
++
++MODULE_AUTHOR("David Knell <david.knell@gmail.com>");
++MODULE_DESCRIPTION("ALSA ASoC Machine Driver for PiFi-40");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/bcm27xx/patches-5.4/950-1002-dwc_otg-Minimise-header-and-fix-build-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-1002-dwc_otg-Minimise-header-and-fix-build-warnings.patch
new file mode 100644 (file)
index 0000000..233b9f3
--- /dev/null
@@ -0,0 +1,747 @@
+From ed478a5013976948e94834244d8e5c0abcaab5c3 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 27 Oct 2020 09:59:49 +0000
+Subject: [PATCH] dwc_otg: Minimise header and fix build warnings
+
+Delete a large amount of unused declaration from "usb.h", some of which
+were causing build warnings, and get the module building cleanly.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/usb/host/dwc_common_port/usb.h       | 664 -------------------
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c |   4 +-
+ drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c  |   2 +-
+ 3 files changed, 3 insertions(+), 667 deletions(-)
+
+--- a/drivers/usb/host/dwc_common_port/usb.h
++++ b/drivers/usb/host/dwc_common_port/usb.h
+@@ -55,12 +55,6 @@ typedef u_int8_t uByte;
+ typedef u_int8_t uWord[2];
+ typedef u_int8_t uDWord[4];
+-#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
+-#define UCONSTW(x)    { (x) & 0xff, ((x) >> 8) & 0xff }
+-#define UCONSTDW(x)   { (x) & 0xff, ((x) >> 8) & 0xff, \
+-                        ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
+-
+-#if 1
+ #define UGETW(w) ((w)[0] | ((w)[1] << 8))
+ #define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
+ #define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
+@@ -68,31 +62,6 @@ typedef u_int8_t uDWord[4];
+                    (w)[1] = (u_int8_t)((v) >> 8), \
+                    (w)[2] = (u_int8_t)((v) >> 16), \
+                    (w)[3] = (u_int8_t)((v) >> 24))
+-#else
+-/*
+- * On little-endian machines that can handle unanliged accesses
+- * (e.g. i386) these macros can be replaced by the following.
+- */
+-#define UGETW(w) (*(u_int16_t *)(w))
+-#define USETW(w,v) (*(u_int16_t *)(w) = (v))
+-#define UGETDW(w) (*(u_int32_t *)(w))
+-#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
+-#endif
+-
+-/*
+- * Macros for accessing UAS IU fields, which are big-endian
+- */
+-#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
+-#define IUCONSTW(x)   { ((x) >> 8) & 0xff, (x) & 0xff }
+-#define IUCONSTDW(x)  { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
+-                      ((x) >> 8) & 0xff, (x) & 0xff }
+-#define IUGETW(w) (((w)[0] << 8) | (w)[1])
+-#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
+-#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
+-#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
+-                    (w)[1] = (u_int8_t)((v) >> 16), \
+-                    (w)[2] = (u_int8_t)((v) >> 8), \
+-                    (w)[3] = (u_int8_t)(v))
+ #define UPACKED __attribute__((__packed__))
+@@ -119,29 +88,6 @@ typedef struct {
+ #define UT_ENDPOINT           0x02
+ #define UT_OTHER              0x03
+-#define UT_READ_DEVICE                (UT_READ  | UT_STANDARD | UT_DEVICE)
+-#define UT_READ_INTERFACE     (UT_READ  | UT_STANDARD | UT_INTERFACE)
+-#define UT_READ_ENDPOINT      (UT_READ  | UT_STANDARD | UT_ENDPOINT)
+-#define UT_WRITE_DEVICE               (UT_WRITE | UT_STANDARD | UT_DEVICE)
+-#define UT_WRITE_INTERFACE    (UT_WRITE | UT_STANDARD | UT_INTERFACE)
+-#define UT_WRITE_ENDPOINT     (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
+-#define UT_READ_CLASS_DEVICE  (UT_READ  | UT_CLASS | UT_DEVICE)
+-#define UT_READ_CLASS_INTERFACE       (UT_READ  | UT_CLASS | UT_INTERFACE)
+-#define UT_READ_CLASS_OTHER   (UT_READ  | UT_CLASS | UT_OTHER)
+-#define UT_READ_CLASS_ENDPOINT        (UT_READ  | UT_CLASS | UT_ENDPOINT)
+-#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE)
+-#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
+-#define UT_WRITE_CLASS_OTHER  (UT_WRITE | UT_CLASS | UT_OTHER)
+-#define UT_WRITE_CLASS_ENDPOINT       (UT_WRITE | UT_CLASS | UT_ENDPOINT)
+-#define UT_READ_VENDOR_DEVICE (UT_READ  | UT_VENDOR | UT_DEVICE)
+-#define UT_READ_VENDOR_INTERFACE (UT_READ  | UT_VENDOR | UT_INTERFACE)
+-#define UT_READ_VENDOR_OTHER  (UT_READ  | UT_VENDOR | UT_OTHER)
+-#define UT_READ_VENDOR_ENDPOINT       (UT_READ  | UT_VENDOR | UT_ENDPOINT)
+-#define UT_WRITE_VENDOR_DEVICE        (UT_WRITE | UT_VENDOR | UT_DEVICE)
+-#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
+-#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER)
+-#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
+-
+ /* Requests */
+ #define UR_GET_STATUS         0x00
+ #define  USTAT_STANDARD_STATUS  0x00
+@@ -243,71 +189,6 @@ typedef struct {
+ typedef struct {
+       uByte           bLength;
+       uByte           bDescriptorType;
+-      uByte           bDescriptorSubtype;
+-} UPACKED usb_descriptor_t;
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-} UPACKED usb_descriptor_header_t;
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-      uWord           bcdUSB;
+-#define UD_USB_2_0            0x0200
+-#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
+-      uByte           bDeviceClass;
+-      uByte           bDeviceSubClass;
+-      uByte           bDeviceProtocol;
+-      uByte           bMaxPacketSize;
+-      /* The fields below are not part of the initial descriptor. */
+-      uWord           idVendor;
+-      uWord           idProduct;
+-      uWord           bcdDevice;
+-      uByte           iManufacturer;
+-      uByte           iProduct;
+-      uByte           iSerialNumber;
+-      uByte           bNumConfigurations;
+-} UPACKED usb_device_descriptor_t;
+-#define USB_DEVICE_DESCRIPTOR_SIZE 18
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-      uWord           wTotalLength;
+-      uByte           bNumInterface;
+-      uByte           bConfigurationValue;
+-      uByte           iConfiguration;
+-#define UC_ATT_ONE            (1 << 7)        /* must be set */
+-#define UC_ATT_SELFPOWER      (1 << 6)        /* self powered */
+-#define UC_ATT_WAKEUP         (1 << 5)        /* can wakeup */
+-#define UC_ATT_BATTERY                (1 << 4)        /* battery powered */
+-      uByte           bmAttributes;
+-#define UC_BUS_POWERED                0x80
+-#define UC_SELF_POWERED               0x40
+-#define UC_REMOTE_WAKEUP      0x20
+-      uByte           bMaxPower; /* max current in 2 mA units */
+-#define UC_POWER_FACTOR 2
+-} UPACKED usb_config_descriptor_t;
+-#define USB_CONFIG_DESCRIPTOR_SIZE 9
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-      uByte           bInterfaceNumber;
+-      uByte           bAlternateSetting;
+-      uByte           bNumEndpoints;
+-      uByte           bInterfaceClass;
+-      uByte           bInterfaceSubClass;
+-      uByte           bInterfaceProtocol;
+-      uByte           iInterface;
+-} UPACKED usb_interface_descriptor_t;
+-#define USB_INTERFACE_DESCRIPTOR_SIZE 9
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+       uByte           bEndpointAddress;
+ #define UE_GET_DIR(a) ((a) & 0x80)
+ #define UE_SET_DIR(a,d)       ((a) | (((d)&1) << 7))
+@@ -332,27 +213,6 @@ typedef struct {
+ } UPACKED usb_endpoint_descriptor_t;
+ #define USB_ENDPOINT_DESCRIPTOR_SIZE 7
+-typedef struct ss_endpoint_companion_descriptor {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bMaxBurst;
+-#define USSE_GET_MAX_STREAMS(a)               ((a) & 0x1f)
+-#define USSE_SET_MAX_STREAMS(a, b)    ((a) | ((b) & 0x1f))
+-#define USSE_GET_MAX_PACKET_NUM(a)    ((a) & 0x03)
+-#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03))
+-      uByte bmAttributes;
+-      uWord wBytesPerInterval;
+-} UPACKED ss_endpoint_companion_descriptor_t;
+-#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-      uWord           bString[127];
+-} UPACKED usb_string_descriptor_t;
+-#define USB_MAX_STRING_LEN 128
+-#define USB_LANGUAGE_TABLE 0  /* # of the string language id table */
+-
+ /* Hub specific request */
+ #define UR_GET_BUS_STATE      0x02
+ #define UR_CLEAR_TT_BUFFER    0x08
+@@ -411,530 +271,6 @@ typedef struct {
+ } UPACKED usb_hub_descriptor_t;
+ #define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-      uWord           bcdUSB;
+-      uByte           bDeviceClass;
+-      uByte           bDeviceSubClass;
+-      uByte           bDeviceProtocol;
+-      uByte           bMaxPacketSize0;
+-      uByte           bNumConfigurations;
+-      uByte           bReserved;
+-} UPACKED usb_device_qualifier_t;
+-#define USB_DEVICE_QUALIFIER_SIZE 10
+-
+-typedef struct {
+-      uByte           bLength;
+-      uByte           bDescriptorType;
+-      uByte           bmAttributes;
+-#define UOTG_SRP      0x01
+-#define UOTG_HNP      0x02
+-} UPACKED usb_otg_descriptor_t;
+-
+-/* OTG feature selectors */
+-#define UOTG_B_HNP_ENABLE     3
+-#define UOTG_A_HNP_SUPPORT    4
+-#define UOTG_A_ALT_HNP_SUPPORT        5
+-
+-typedef struct {
+-      uWord           wStatus;
+-/* Device status flags */
+-#define UDS_SELF_POWERED              0x0001
+-#define UDS_REMOTE_WAKEUP             0x0002
+-/* Endpoint status flags */
+-#define UES_HALT                      0x0001
+-} UPACKED usb_status_t;
+-
+-typedef struct {
+-      uWord           wHubStatus;
+-#define UHS_LOCAL_POWER                       0x0001
+-#define UHS_OVER_CURRENT              0x0002
+-      uWord           wHubChange;
+-} UPACKED usb_hub_status_t;
+-
+-typedef struct {
+-      uWord           wPortStatus;
+-#define UPS_CURRENT_CONNECT_STATUS    0x0001
+-#define UPS_PORT_ENABLED              0x0002
+-#define UPS_SUSPEND                   0x0004
+-#define UPS_OVERCURRENT_INDICATOR     0x0008
+-#define UPS_RESET                     0x0010
+-#define UPS_PORT_POWER                        0x0100
+-#define UPS_LOW_SPEED                 0x0200
+-#define UPS_HIGH_SPEED                        0x0400
+-#define UPS_PORT_TEST                 0x0800
+-#define UPS_PORT_INDICATOR            0x1000
+-      uWord           wPortChange;
+-#define UPS_C_CONNECT_STATUS          0x0001
+-#define UPS_C_PORT_ENABLED            0x0002
+-#define UPS_C_SUSPEND                 0x0004
+-#define UPS_C_OVERCURRENT_INDICATOR   0x0008
+-#define UPS_C_PORT_RESET              0x0010
+-} UPACKED usb_port_status_t;
+-
+-#ifdef _MSC_VER
+-#include <poppack.h>
+-#endif
+-
+-/* Device class codes */
+-#define UDCLASS_IN_INTERFACE  0x00
+-#define UDCLASS_COMM          0x02
+-#define UDCLASS_HUB           0x09
+-#define  UDSUBCLASS_HUB               0x00
+-#define  UDPROTO_FSHUB                0x00
+-#define  UDPROTO_HSHUBSTT     0x01
+-#define  UDPROTO_HSHUBMTT     0x02
+-#define UDCLASS_DIAGNOSTIC    0xdc
+-#define UDCLASS_WIRELESS      0xe0
+-#define  UDSUBCLASS_RF                0x01
+-#define   UDPROTO_BLUETOOTH   0x01
+-#define UDCLASS_VENDOR                0xff
+-
+-/* Interface class codes */
+-#define UICLASS_UNSPEC                0x00
+-
+-#define UICLASS_AUDIO         0x01
+-#define  UISUBCLASS_AUDIOCONTROL      1
+-#define  UISUBCLASS_AUDIOSTREAM               2
+-#define  UISUBCLASS_MIDISTREAM                3
+-
+-#define UICLASS_CDC           0x02 /* communication */
+-#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1
+-#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL    2
+-#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL   3
+-#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL        4
+-#define  UISUBCLASS_CAPI_CONTROLMODEL         5
+-#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
+-#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
+-#define   UIPROTO_CDC_AT                      1
+-
+-#define UICLASS_HID           0x03
+-#define  UISUBCLASS_BOOT      1
+-#define  UIPROTO_BOOT_KEYBOARD        1
+-
+-#define UICLASS_PHYSICAL      0x05
+-
+-#define UICLASS_IMAGE         0x06
+-
+-#define UICLASS_PRINTER               0x07
+-#define  UISUBCLASS_PRINTER   1
+-#define  UIPROTO_PRINTER_UNI  1
+-#define  UIPROTO_PRINTER_BI   2
+-#define  UIPROTO_PRINTER_1284 3
+-
+-#define UICLASS_MASS          0x08
+-#define  UISUBCLASS_RBC               1
+-#define  UISUBCLASS_SFF8020I  2
+-#define  UISUBCLASS_QIC157    3
+-#define  UISUBCLASS_UFI               4
+-#define  UISUBCLASS_SFF8070I  5
+-#define  UISUBCLASS_SCSI      6
+-#define  UIPROTO_MASS_CBI_I   0
+-#define  UIPROTO_MASS_CBI     1
+-#define  UIPROTO_MASS_BBB_OLD 2       /* Not in the spec anymore */
+-#define  UIPROTO_MASS_BBB     80      /* 'P' for the Iomega Zip drive */
+-
+-#define UICLASS_HUB           0x09
+-#define  UISUBCLASS_HUB               0
+-#define  UIPROTO_FSHUB                0
+-#define  UIPROTO_HSHUBSTT     0 /* Yes, same as previous */
+-#define  UIPROTO_HSHUBMTT     1
+-
+-#define UICLASS_CDC_DATA      0x0a
+-#define  UISUBCLASS_DATA              0
+-#define   UIPROTO_DATA_ISDNBRI                0x30    /* Physical iface */
+-#define   UIPROTO_DATA_HDLC           0x31    /* HDLC */
+-#define   UIPROTO_DATA_TRANSPARENT    0x32    /* Transparent */
+-#define   UIPROTO_DATA_Q921M          0x50    /* Management for Q921 */
+-#define   UIPROTO_DATA_Q921           0x51    /* Data for Q921 */
+-#define   UIPROTO_DATA_Q921TM         0x52    /* TEI multiplexer for Q921 */
+-#define   UIPROTO_DATA_V42BIS         0x90    /* Data compression */
+-#define   UIPROTO_DATA_Q931           0x91    /* Euro-ISDN */
+-#define   UIPROTO_DATA_V120           0x92    /* V.24 rate adaption */
+-#define   UIPROTO_DATA_CAPI           0x93    /* CAPI 2.0 commands */
+-#define   UIPROTO_DATA_HOST_BASED     0xfd    /* Host based driver */
+-#define   UIPROTO_DATA_PUF            0xfe    /* see Prot. Unit Func. Desc.*/
+-#define   UIPROTO_DATA_VENDOR         0xff    /* Vendor specific */
+-
+-#define UICLASS_SMARTCARD     0x0b
+-
+-/*#define UICLASS_FIRM_UPD    0x0c*/
+-
+-#define UICLASS_SECURITY      0x0d
+-
+-#define UICLASS_DIAGNOSTIC    0xdc
+-
+-#define UICLASS_WIRELESS      0xe0
+-#define  UISUBCLASS_RF                        0x01
+-#define   UIPROTO_BLUETOOTH           0x01
+-
+-#define UICLASS_APPL_SPEC     0xfe
+-#define  UISUBCLASS_FIRMWARE_DOWNLOAD 1
+-#define  UISUBCLASS_IRDA              2
+-#define  UIPROTO_IRDA                 0
+-
+-#define UICLASS_VENDOR                0xff
+-
+-#define USB_HUB_MAX_DEPTH 5
+-
+-/*
+- * Minimum time a device needs to be powered down to go through
+- * a power cycle.  XXX Are these time in the spec?
+- */
+-#define USB_POWER_DOWN_TIME   200 /* ms */
+-#define USB_PORT_POWER_DOWN_TIME      100 /* ms */
+-
+-#if 0
+-/* These are the values from the spec. */
+-#define USB_PORT_RESET_DELAY  10  /* ms */
+-#define USB_PORT_ROOT_RESET_DELAY 50  /* ms */
+-#define USB_PORT_RESET_RECOVERY       10  /* ms */
+-#define USB_PORT_POWERUP_DELAY        100 /* ms */
+-#define USB_SET_ADDRESS_SETTLE        2   /* ms */
+-#define USB_RESUME_DELAY      (20*5)  /* ms */
+-#define USB_RESUME_WAIT               10  /* ms */
+-#define USB_RESUME_RECOVERY   10  /* ms */
+-#define USB_EXTRA_POWER_UP_TIME       0   /* ms */
+-#else
+-/* Allow for marginal (i.e. non-conforming) devices. */
+-#define USB_PORT_RESET_DELAY  50  /* ms */
+-#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
+-#define USB_PORT_RESET_RECOVERY       250  /* ms */
+-#define USB_PORT_POWERUP_DELAY        300 /* ms */
+-#define USB_SET_ADDRESS_SETTLE        10  /* ms */
+-#define USB_RESUME_DELAY      (50*5)  /* ms */
+-#define USB_RESUME_WAIT               50  /* ms */
+-#define USB_RESUME_RECOVERY   50  /* ms */
+-#define USB_EXTRA_POWER_UP_TIME       20  /* ms */
+-#endif
+-
+-#define USB_MIN_POWER         100 /* mA */
+-#define USB_MAX_POWER         500 /* mA */
+-
+-#define USB_BUS_RESET_DELAY   100 /* ms XXX?*/
+-
+-#define USB_UNCONFIG_NO 0
+-#define USB_UNCONFIG_INDEX (-1)
+-
+-/*** ioctl() related stuff ***/
+-
+-struct usb_ctl_request {
+-      int     ucr_addr;
+-      usb_device_request_t ucr_request;
+-      void    *ucr_data;
+-      int     ucr_flags;
+-#define USBD_SHORT_XFER_OK    0x04    /* allow short reads */
+-      int     ucr_actlen;             /* actual length transferred */
+-};
+-
+-struct usb_alt_interface {
+-      int     uai_config_index;
+-      int     uai_interface_index;
+-      int     uai_alt_no;
+-};
+-
+-#define USB_CURRENT_CONFIG_INDEX (-1)
+-#define USB_CURRENT_ALT_INDEX (-1)
+-
+-struct usb_config_desc {
+-      int     ucd_config_index;
+-      usb_config_descriptor_t ucd_desc;
+-};
+-
+-struct usb_interface_desc {
+-      int     uid_config_index;
+-      int     uid_interface_index;
+-      int     uid_alt_index;
+-      usb_interface_descriptor_t uid_desc;
+-};
+-
+-struct usb_endpoint_desc {
+-      int     ued_config_index;
+-      int     ued_interface_index;
+-      int     ued_alt_index;
+-      int     ued_endpoint_index;
+-      usb_endpoint_descriptor_t ued_desc;
+-};
+-
+-struct usb_full_desc {
+-      int     ufd_config_index;
+-      u_int   ufd_size;
+-      u_char  *ufd_data;
+-};
+-
+-struct usb_string_desc {
+-      int     usd_string_index;
+-      int     usd_language_id;
+-      usb_string_descriptor_t usd_desc;
+-};
+-
+-struct usb_ctl_report_desc {
+-      int     ucrd_size;
+-      u_char  ucrd_data[1024];        /* filled data size will vary */
+-};
+-
+-typedef struct { u_int32_t cookie; } usb_event_cookie_t;
+-
+-#define USB_MAX_DEVNAMES 4
+-#define USB_MAX_DEVNAMELEN 16
+-struct usb_device_info {
+-      u_int8_t        udi_bus;
+-      u_int8_t        udi_addr;       /* device address */
+-      usb_event_cookie_t udi_cookie;
+-      char            udi_product[USB_MAX_STRING_LEN];
+-      char            udi_vendor[USB_MAX_STRING_LEN];
+-      char            udi_release[8];
+-      u_int16_t       udi_productNo;
+-      u_int16_t       udi_vendorNo;
+-      u_int16_t       udi_releaseNo;
+-      u_int8_t        udi_class;
+-      u_int8_t        udi_subclass;
+-      u_int8_t        udi_protocol;
+-      u_int8_t        udi_config;
+-      u_int8_t        udi_speed;
+-#define USB_SPEED_UNKNOWN     0
+-#define USB_SPEED_LOW         1
+-#define USB_SPEED_FULL                2
+-#define USB_SPEED_HIGH                3
+-#define USB_SPEED_VARIABLE    4
+-#define USB_SPEED_SUPER               5
+-      int             udi_power;      /* power consumption in mA, 0 if selfpowered */
+-      int             udi_nports;
+-      char            udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
+-      u_int8_t        udi_ports[16];/* hub only: addresses of devices on ports */
+-#define USB_PORT_ENABLED 0xff
+-#define USB_PORT_SUSPENDED 0xfe
+-#define USB_PORT_POWERED 0xfd
+-#define USB_PORT_DISABLED 0xfc
+-};
+-
+-struct usb_ctl_report {
+-      int     ucr_report;
+-      u_char  ucr_data[1024]; /* filled data size will vary */
+-};
+-
+-struct usb_device_stats {
+-      u_long  uds_requests[4];        /* indexed by transfer type UE_* */
+-};
+-
+-#define WUSB_MIN_IE                   0x80
+-#define WUSB_WCTA_IE                  0x80
+-#define WUSB_WCONNECTACK_IE           0x81
+-#define WUSB_WHOSTINFO_IE             0x82
+-#define  WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
+-#define   WUHI_CA_RECONN              0x00
+-#define   WUHI_CA_LIMITED             0x01
+-#define   WUHI_CA_ALL                 0x03
+-#define  WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
+-#define WUSB_WCHCHANGEANNOUNCE_IE     0x83
+-#define WUSB_WDEV_DISCONNECT_IE               0x84
+-#define WUSB_WHOST_DISCONNECT_IE      0x85
+-#define WUSB_WRELEASE_CHANNEL_IE      0x86
+-#define WUSB_WWORK_IE                 0x87
+-#define WUSB_WCHANNEL_STOP_IE         0x88
+-#define WUSB_WDEV_KEEPALIVE_IE                0x89
+-#define WUSB_WISOCH_DISCARD_IE                0x8A
+-#define WUSB_WRESETDEVICE_IE          0x8B
+-#define WUSB_WXMIT_PACKET_ADJUST_IE   0x8C
+-#define WUSB_MAX_IE                   0x8C
+-
+-/* Device Notification Types */
+-
+-#define WUSB_DN_MIN                   0x01
+-#define WUSB_DN_CONNECT                       0x01
+-# define WUSB_DA_OLDCONN      0x00
+-# define WUSB_DA_NEWCONN      0x01
+-# define WUSB_DA_SELF_BEACON  0x02
+-# define WUSB_DA_DIR_BEACON   0x04
+-# define WUSB_DA_NO_BEACON    0x06
+-#define WUSB_DN_DISCONNECT            0x02
+-#define WUSB_DN_EPRDY                 0x03
+-#define WUSB_DN_MASAVAILCHANGED               0x04
+-#define WUSB_DN_REMOTEWAKEUP          0x05
+-#define WUSB_DN_SLEEP                 0x06
+-#define WUSB_DN_ALIVE                 0x07
+-#define WUSB_DN_MAX                   0x07
+-
+-#ifdef _MSC_VER
+-#include <pshpack1.h>
+-#endif
+-
+-/* WUSB Handshake Data.  Used during the SET/GET HANDSHAKE requests */
+-typedef struct wusb_hndshk_data {
+-      uByte bMessageNumber;
+-      uByte bStatus;
+-      uByte tTKID[3];
+-      uByte bReserved;
+-      uByte CDID[16];
+-      uByte Nonce[16];
+-      uByte MIC[8];
+-} UPACKED wusb_hndshk_data_t;
+-#define WUSB_HANDSHAKE_LEN_FOR_MIC    38
+-
+-/* WUSB Connection Context */
+-typedef struct wusb_conn_context {
+-      uByte CHID [16];
+-      uByte CDID [16];
+-      uByte CK [16];
+-} UPACKED wusb_conn_context_t;
+-
+-/* WUSB Security Descriptor */
+-typedef struct wusb_security_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uWord wTotalLength;
+-      uByte bNumEncryptionTypes;
+-} UPACKED wusb_security_desc_t;
+-
+-/* WUSB Encryption Type Descriptor */
+-typedef struct wusb_encrypt_type_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-
+-      uByte bEncryptionType;
+-#define WUETD_UNSECURE                0
+-#define WUETD_WIRED           1
+-#define WUETD_CCM_1           2
+-#define WUETD_RSA_1           3
+-
+-      uByte bEncryptionValue;
+-      uByte bAuthKeyIndex;
+-} UPACKED wusb_encrypt_type_desc_t;
+-
+-/* WUSB Key Descriptor */
+-typedef struct wusb_key_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte tTKID[3];
+-      uByte bReserved;
+-      uByte KeyData[1];       /* variable length */
+-} UPACKED wusb_key_desc_t;
+-
+-/* WUSB BOS Descriptor (Binary device Object Store) */
+-typedef struct wusb_bos_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uWord wTotalLength;
+-      uByte bNumDeviceCaps;
+-} UPACKED wusb_bos_desc_t;
+-
+-#define USB_DEVICE_CAPABILITY_20_EXTENSION    0x02
+-typedef struct usb_dev_cap_20_ext_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bDevCapabilityType;
+-#define USB_20_EXT_LPM                                0x02
+-      uDWord bmAttributes;
+-} UPACKED usb_dev_cap_20_ext_desc_t;
+-
+-#define USB_DEVICE_CAPABILITY_SS_USB          0x03
+-typedef struct usb_dev_cap_ss_usb {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bDevCapabilityType;
+-#define USB_DC_SS_USB_LTM_CAPABLE             0x02
+-      uByte bmAttributes;
+-#define USB_DC_SS_USB_SPEED_SUPPORT_LOW               0x01
+-#define USB_DC_SS_USB_SPEED_SUPPORT_FULL      0x02
+-#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH      0x04
+-#define USB_DC_SS_USB_SPEED_SUPPORT_SS                0x08
+-      uWord wSpeedsSupported;
+-      uByte bFunctionalitySupport;
+-      uByte bU1DevExitLat;
+-      uWord wU2DevExitLat;
+-} UPACKED usb_dev_cap_ss_usb_t;
+-
+-#define USB_DEVICE_CAPABILITY_CONTAINER_ID    0x04
+-typedef struct usb_dev_cap_container_id {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bDevCapabilityType;
+-      uByte bReserved;
+-      uByte containerID[16];
+-} UPACKED usb_dev_cap_container_id_t;
+-
+-/* Device Capability Type Codes */
+-#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
+-
+-/* Device Capability Descriptor */
+-typedef struct wusb_dev_cap_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bDevCapabilityType;
+-      uByte caps[1];  /* Variable length */
+-} UPACKED wusb_dev_cap_desc_t;
+-
+-/* Device Capability Descriptor */
+-typedef struct wusb_dev_cap_uwb_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bDevCapabilityType;
+-      uByte bmAttributes;
+-      uWord wPHYRates;        /* Bitmap */
+-      uByte bmTFITXPowerInfo;
+-      uByte bmFFITXPowerInfo;
+-      uWord bmBandGroup;
+-      uByte bReserved;
+-} UPACKED wusb_dev_cap_uwb_desc_t;
+-
+-/* Wireless USB Endpoint Companion Descriptor */
+-typedef struct wusb_endpoint_companion_desc {
+-      uByte bLength;
+-      uByte bDescriptorType;
+-      uByte bMaxBurst;
+-      uByte bMaxSequence;
+-      uWord wMaxStreamDelay;
+-      uWord wOverTheAirPacketSize;
+-      uByte bOverTheAirInterval;
+-      uByte bmCompAttributes;
+-} UPACKED wusb_endpoint_companion_desc_t;
+-
+-/* Wireless USB Numeric Association M1 Data Structure */
+-typedef struct wusb_m1_data {
+-      uByte version;
+-      uWord langId;
+-      uByte deviceFriendlyNameLength;
+-      uByte sha_256_m3[32];
+-      uByte deviceFriendlyName[256];
+-} UPACKED wusb_m1_data_t;
+-
+-typedef struct wusb_m2_data {
+-      uByte version;
+-      uWord langId;
+-      uByte hostFriendlyNameLength;
+-      uByte pkh[384];
+-      uByte hostFriendlyName[256];
+-} UPACKED wusb_m2_data_t;
+-
+-typedef struct wusb_m3_data {
+-      uByte pkd[384];
+-      uByte nd;
+-} UPACKED wusb_m3_data_t;
+-
+-typedef struct wusb_m4_data {
+-      uDWord _attributeTypeIdAndLength_1;
+-      uWord  associationTypeId;
+-
+-      uDWord _attributeTypeIdAndLength_2;
+-      uWord  associationSubTypeId;
+-
+-      uDWord _attributeTypeIdAndLength_3;
+-      uDWord length;
+-
+-      uDWord _attributeTypeIdAndLength_4;
+-      uDWord associationStatus;
+-
+-      uDWord _attributeTypeIdAndLength_5;
+-      uByte  chid[16];
+-
+-      uDWord _attributeTypeIdAndLength_6;
+-      uByte  cdid[16];
+-
+-      uDWord _attributeTypeIdAndLength_7;
+-      uByte  bandGroups[2];
+-} UPACKED wusb_m4_data_t;
+-
+ #ifdef _MSC_VER
+ #include <poppack.h>
+ #endif
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -457,8 +457,8 @@ static void hcd_init_fiq(void *cookie)
+                       otg_dev->os_dep.mphi_base + 0x1f0;
+               dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr =
+                       otg_dev->os_dep.mphi_base + 0x1f4;
+-              DWC_WARN("Fake MPHI regs_base at 0x%08x",
+-                       (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
++              DWC_WARN("Fake MPHI regs_base at %px",
++                       dwc_otg_hcd->fiq_state->mphi_regs.base);
+       } else {
+               dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
+                       otg_dev->os_dep.mphi_base + 0x4c;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
+@@ -3377,7 +3377,7 @@ void predict_nextep_seq( dwc_otg_core_if
+       dtknq1_data_t dtknqr1;
+       uint32_t in_tkn_epnums[4];
+       uint8_t seqnum[MAX_EPS_CHANNELS];
+-      uint8_t intkn_seq[TOKEN_Q_DEPTH];
++      uint8_t intkn_seq[1 << 5];
+       grstctl_t resetctl = {.d32 = 0 };
+       uint8_t temp;
+       int ndx = 0;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1003-gpio-fsm-Fix-a-build-warning.patch b/target/linux/bcm27xx/patches-5.4/950-1003-gpio-fsm-Fix-a-build-warning.patch
new file mode 100644 (file)
index 0000000..d9ebc3a
--- /dev/null
@@ -0,0 +1,22 @@
+From 60f17bc7d9100d7c3296987498a9f2d6c13f3f02 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 27 Oct 2020 12:10:04 +0000
+Subject: [PATCH] gpio-fsm: Fix a build warning
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/gpio/gpio-fsm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-fsm.c
++++ b/drivers/gpio/gpio-fsm.c
+@@ -956,7 +956,8 @@ static int gpio_fsm_probe(struct platfor
+       // add reserved words to the symbol table
+       for (i = 0; i < ARRAY_SIZE(reserved_symbols); i++) {
+               if (reserved_symbols[i])
+-                      add_symbol(&gf->symtab, reserved_symbols[i], (void *)i);
++                      add_symbol(&gf->symtab, reserved_symbols[i],
++                                 (void *)(uintptr_t)i);
+       }
+       // parse the state
diff --git a/target/linux/bcm27xx/patches-5.4/950-1004-rpivid_h625-Fix-build-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-1004-rpivid_h625-Fix-build-warnings.patch
new file mode 100644 (file)
index 0000000..375f1ca
--- /dev/null
@@ -0,0 +1,68 @@
+From c23b30df4bcafaa1a2bca210bc09f65c01ace375 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 27 Oct 2020 12:10:40 +0000
+Subject: [PATCH] rpivid_h625: Fix build warnings
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/staging/media/rpivid/rpivid_h265.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/staging/media/rpivid/rpivid_h265.c
++++ b/drivers/staging/media/rpivid/rpivid_h265.c
+@@ -1341,10 +1341,10 @@ static int frame_end(struct rpivid_dev *
+               if (gptr_realloc_new(dev, de->cmd_copy_gptr, cmd_alloc)) {
+                       v4l2_err(&dev->v4l2_dev,
+-                               "Alloc cmd buffer (%d): FAILED\n", cmd_alloc);
++                               "Alloc cmd buffer (%zu): FAILED\n", cmd_alloc);
+                       return -ENOMEM;
+               }
+-              v4l2_info(&dev->v4l2_dev, "Alloc cmd buffer (%d): OK\n",
++              v4l2_info(&dev->v4l2_dev, "Alloc cmd buffer (%zu): OK\n",
+                         cmd_alloc);
+       }
+@@ -1696,12 +1696,12 @@ static void rpivid_h265_setup(struct rpi
+                                      bits_alloc,
+                                      DMA_ATTR_FORCE_CONTIGUOUS) != 0) {
+                               v4l2_err(&dev->v4l2_dev,
+-                                       "Unable to alloc buf (%d) for bit copy\n",
++                                       "Unable to alloc buf (%zu) for bit copy\n",
+                                        bits_alloc);
+                               goto fail;
+                       }
+                       v4l2_info(&dev->v4l2_dev,
+-                                "Alloc buf (%d) for bit copy OK\n",
++                                "Alloc buf (%zu) for bit copy OK\n",
+                                 bits_alloc);
+               }
+       }
+@@ -1995,11 +1995,11 @@ static void phase1_thread(struct rpivid_
+       if (de->p1_status & STATUS_PU_EXHAUSTED) {
+               if (gptr_realloc_new(dev, pu_gptr, next_size(pu_gptr->size))) {
+                       v4l2_err(&dev->v4l2_dev,
+-                               "%s: PU realloc (%#x) failed\n",
++                               "%s: PU realloc (%zx) failed\n",
+                                __func__, pu_gptr->size);
+                       goto fail;
+               }
+-              v4l2_info(&dev->v4l2_dev, "%s: PU realloc (%#x) OK\n",
++              v4l2_info(&dev->v4l2_dev, "%s: PU realloc (%zx) OK\n",
+                         __func__, pu_gptr->size);
+       }
+@@ -2007,11 +2007,11 @@ static void phase1_thread(struct rpivid_
+               if (gptr_realloc_new(dev, coeff_gptr,
+                                    next_size(coeff_gptr->size))) {
+                       v4l2_err(&dev->v4l2_dev,
+-                               "%s: Coeff realloc (%#x) failed\n",
++                               "%s: Coeff realloc (%zx) failed\n",
+                                __func__, coeff_gptr->size);
+                       goto fail;
+               }
+-              v4l2_info(&dev->v4l2_dev, "%s: Coeff realloc (%#x) OK\n",
++              v4l2_info(&dev->v4l2_dev, "%s: Coeff realloc (%zx) OK\n",
+                         __func__, coeff_gptr->size);
+       }
diff --git a/target/linux/bcm27xx/patches-5.4/950-1005-dwc_otg-Fix-more-build-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-1005-dwc_otg-Fix-more-build-warnings.patch
new file mode 100644 (file)
index 0000000..a9f5605
--- /dev/null
@@ -0,0 +1,149 @@
+From 9b899afd231b7dde6084092cf46dd15c05ed8a5c Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 27 Oct 2020 12:11:56 +0000
+Subject: [PATCH] dwc_otg: Fix more build warnings
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c  | 10 +++++----
+ drivers/usb/host/dwc_otg/dwc_otg_hcd.c      | 23 ++++++++++++++-------
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c |  3 ++-
+ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c |  8 +++----
+ 4 files changed, 27 insertions(+), 17 deletions(-)
+
+--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+@@ -240,7 +240,8 @@ static int notrace fiq_increment_dma_buf
+       hcdma_data_t hcdma;
+       int i = st->channel[n].dma_info.index;
+       int len;
+-      struct fiq_dma_blob *blob = (struct fiq_dma_blob *) st->dma_base;
++      struct fiq_dma_blob *blob =
++              (struct fiq_dma_blob *)(uintptr_t)st->dma_base;
+       len = fiq_get_xfer_len(st, n);
+       fiq_print(FIQDBG_INT, st, "LEN: %03d", len);
+@@ -249,7 +250,7 @@ static int notrace fiq_increment_dma_buf
+       if (i > 6)
+               BUG();
+-      hcdma.d32 = (dma_addr_t) &blob->channel[n].index[i].buf[0];
++      hcdma.d32 = (u32)(uintptr_t)&blob->channel[n].index[i].buf[0];
+       FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA, hcdma.d32);
+       st->channel[n].dma_info.index = i;
+       return 0;
+@@ -289,7 +290,8 @@ static int notrace fiq_iso_out_advance(s
+       hcsplt_data_t hcsplt;
+       hctsiz_data_t hctsiz;
+       hcdma_data_t hcdma;
+-      struct fiq_dma_blob *blob = (struct fiq_dma_blob *) st->dma_base;
++      struct fiq_dma_blob *blob =
++              (struct fiq_dma_blob *)(uintptr_t)st->dma_base;
+       int last = 0;
+       int i = st->channel[n].dma_info.index;
+@@ -301,7 +303,7 @@ static int notrace fiq_iso_out_advance(s
+               last = 1;
+       /* New DMA address - address of bounce buffer referred to in index */
+-      hcdma.d32 = (dma_addr_t) blob->channel[n].index[i].buf;
++      hcdma.d32 = (u32)(uintptr_t)blob->channel[n].index[i].buf;
+       //hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA);
+       //hcdma.d32 += st->channel[n].dma_info.slot_len[i];
+       fiq_print(FIQDBG_INT, st, "LAST: %01d ", last);
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -1268,7 +1268,8 @@ static void assign_and_init_hc(dwc_otg_h
+       hc->multi_count = 1;
+       if (hcd->core_if->dma_enable) {
+-              hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
++              hc->xfer_buff =
++                  (uint8_t *)(uintptr_t)urb->dma + urb->actual_length;
+               /* For non-dword aligned case */
+               if (((unsigned long)hc->xfer_buff & 0x3)
+@@ -1312,7 +1313,8 @@ static void assign_and_init_hc(dwc_otg_h
+                       hc->ep_is_in = 0;
+                       hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
+                       if (hcd->core_if->dma_enable) {
+-                              hc->xfer_buff = (uint8_t *) urb->setup_dma;
++                              hc->xfer_buff =
++                                      (uint8_t *)(uintptr_t)urb->setup_dma;
+                       } else {
+                               hc->xfer_buff = (uint8_t *) urb->setup_packet;
+                       }
+@@ -1360,7 +1362,8 @@ static void assign_and_init_hc(dwc_otg_h
+                       hc->xfer_len = 0;
+                       if (hcd->core_if->dma_enable) {
+-                              hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
++                              hc->xfer_buff = (uint8_t *)
++                                      (uintptr_t)hcd->status_buf_dma;
+                       } else {
+                               hc->xfer_buff = (uint8_t *) hcd->status_buf;
+                       }
+@@ -1388,7 +1391,7 @@ static void assign_and_init_hc(dwc_otg_h
+                       frame_desc->status = 0;
+                       if (hcd->core_if->dma_enable) {
+-                              hc->xfer_buff = (uint8_t *) urb->dma;
++                              hc->xfer_buff = (uint8_t *)(uintptr_t)urb->dma;
+                       } else {
+                               hc->xfer_buff = (uint8_t *) urb->buf;
+                       }
+@@ -1569,8 +1572,10 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
+                * Pointer arithmetic on hcd->fiq_state->dma_base (a dma_addr_t)
+                * to point it to the correct offset in the allocated buffers.
+                */
+-              blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
+-              st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
++              blob = (struct fiq_dma_blob *)
++                      (uintptr_t)hcd->fiq_state->dma_base;
++              st->hcdma_copy.d32 =(u32)(uintptr_t)
++                      blob->channel[hc->hc_num].index[0].buf;
+               /* Calculate the max number of CSPLITS such that the FIQ can time out
+                * a transaction if it fails.
+@@ -1625,8 +1630,10 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h
+                        * dma_addr_t) to point it to the correct offset in the
+                        * allocated buffers.
+                        */
+-                      blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
+-                      st->hcdma_copy.d32 = (dma_addr_t) blob->channel[hc->hc_num].index[0].buf;
++                      blob = (struct fiq_dma_blob *)
++                              (uintptr_t)hcd->fiq_state->dma_base;
++                      st->hcdma_copy.d32 = (u32)(uintptr_t)
++                              blob->channel[hc->hc_num].index[0].buf;
+                       /* fixup xfersize to the actual packet size */
+                       st->hctsiz_copy.b.pid = 0;
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
+@@ -620,7 +620,8 @@ static void init_non_isoc_dma_desc(dwc_o
+               if (n_desc) {
+                       /* SG request - more than 1 QTDs */
+-                      hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
++                      hc->xfer_buff = (uint8_t *)(uintptr_t)qtd->urb->dma +
++                                      qtd->urb->actual_length;
+                       hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
+               }
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+@@ -1857,10 +1857,10 @@ static int32_t handle_hc_ahberr_intr(dwc
+       DWC_ERROR("  Max packet size: %d\n",
+                 dwc_otg_hcd_get_mps(&urb->pipe_info));
+       DWC_ERROR("  Data buffer length: %d\n", urb->length);
+-      DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %p\n",
+-                urb->buf, (void *)urb->dma);
+-      DWC_ERROR("  Setup buffer: %p, Setup DMA: %p\n",
+-                urb->setup_packet, (void *)urb->setup_dma);
++      DWC_ERROR("  Transfer buffer: %p, Transfer DMA: %pad\n",
++                urb->buf, &urb->dma);
++      DWC_ERROR("  Setup buffer: %p, Setup DMA: %pad\n",
++                urb->setup_packet, &urb->setup_dma);
+       DWC_ERROR("  Interval: %d\n", urb->interval);
+       /* Core haltes the channel for Descriptor DMA mode */
diff --git a/target/linux/bcm27xx/patches-5.4/950-1006-bcm2708_fb-Fix-a-build-warning.patch b/target/linux/bcm27xx/patches-5.4/950-1006-bcm2708_fb-Fix-a-build-warning.patch
new file mode 100644 (file)
index 0000000..2eb5f78
--- /dev/null
@@ -0,0 +1,22 @@
+From 61ed3659dae5bdb4c7b1120b3ba4efd3e6abff05 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 27 Oct 2020 12:12:22 +0000
+Subject: [PATCH] bcm2708_fb: Fix a build warning
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/video/fbdev/bcm2708_fb.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/fbdev/bcm2708_fb.c
++++ b/drivers/video/fbdev/bcm2708_fb.c
+@@ -705,7 +705,8 @@ static long vc_mem_copy(struct bcm2708_f
+               u8 *q = (u8 *)ioparam->dst + offset;
+               dma_memcpy(fb, bus_addr,
+-                         INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
++                         INTALIAS_L1L2_NONALLOCATING((u32)(uintptr_t)p),
++                                                     size);
+               if (copy_to_user(q, buf, s) != 0) {
+                       pr_err("[%s]: failed to copy-to-user\n", __func__);
+                       rc = -EFAULT;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1007-bcm2835-pcm-Fix-up-multichannel-pcm-audio.patch b/target/linux/bcm27xx/patches-5.4/950-1007-bcm2835-pcm-Fix-up-multichannel-pcm-audio.patch
new file mode 100644 (file)
index 0000000..a41d16e
--- /dev/null
@@ -0,0 +1,55 @@
+From 88bddc0f26024c64e1e17562dea77d8a50e1f1d0 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <popcornmix@gmail.com>
+Date: Tue, 27 Oct 2020 12:24:14 +0000
+Subject: [PATCH] bcm2835-pcm: Fix up multichannel pcm audio
+
+Fixes: a9c1660ff5f02d048c5f31abf1fd1108ccf9ef87
+Signed-off-by: Dom Cobley <popcornmix@gmail.com>
+---
+ .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 21 +++++++++----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
++++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+@@ -14,14 +14,14 @@ static const struct snd_pcm_hardware snd
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_SYNC_APPLPTR),
+       .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+-      .rates = SNDRV_PCM_RATE_CONTINUOUS |  SNDRV_PCM_RATE_8000_192000,
++      .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
+       .rate_min = 8000,
+       .rate_max = 192000,
+       .channels_min = 1,
+-      .channels_max = 2,
+-      .buffer_bytes_max = 128 * 1024,
++      .channels_max = 8,
++      .buffer_bytes_max = 512 * 1024,
+       .period_bytes_min = 1 * 1024,
+-      .period_bytes_max = 128 * 1024,
++      .period_bytes_max = 512 * 1024,
+       .periods_min = 1,
+       .periods_max = 128,
+ };
+@@ -31,16 +31,15 @@ static const struct snd_pcm_hardware snd
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_SYNC_APPLPTR),
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+-      .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+-      SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+-      SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
++      .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
++      SNDRV_PCM_RATE_48000,
+       .rate_min = 44100,
+-      .rate_max = 192000,
++      .rate_max = 48000,
+       .channels_min = 2,
+-      .channels_max = 8,
+-      .buffer_bytes_max = 512 * 1024,
++      .channels_max = 2,
++      .buffer_bytes_max = 128 * 1024,
+       .period_bytes_min = 1 * 1024,
+-      .period_bytes_max = 512 * 1024,
++      .period_bytes_max = 128 * 1024,
+       .periods_min = 1,
+       .periods_max = 128,
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-1008-watchdog-bcm2835-Ignore-params-after-the-partition-n.patch b/target/linux/bcm27xx/patches-5.4/950-1008-watchdog-bcm2835-Ignore-params-after-the-partition-n.patch
new file mode 100644 (file)
index 0000000..44108ec
--- /dev/null
@@ -0,0 +1,29 @@
+From 118538ed52b7dd927226837094d44a5d1cd14ab7 Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.org>
+Date: Thu, 22 Oct 2020 15:30:55 +0100
+Subject: [PATCH] watchdog: bcm2835: Ignore params after the
+ partition number
+
+Use sscanf to extract the partition number and ignore extra parameters
+which are only relevant to other reboot notifiers.
+---
+ drivers/watchdog/bcm2835_wdt.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/watchdog/bcm2835_wdt.c
++++ b/drivers/watchdog/bcm2835_wdt.c
+@@ -126,10 +126,12 @@ static int bcm2835_restart(struct watchd
+ {
+       struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
+-      unsigned long long val;
++      unsigned long val;
+       u8 partition = 0;
+-      if (data && !kstrtoull(data, 0, &val) && val <= 63)
++      // Allow extra arguments separated by spaces after
++      // the partition number.
++      if (data && sscanf(data, "%lu", &val) && val < 63)
+               partition = val;
+       __bcm2835_restart(wdt, partition);
diff --git a/target/linux/bcm27xx/patches-5.4/950-1009-firmware-raspberrypi-Add-support-for-tryonce-reboot-.patch b/target/linux/bcm27xx/patches-5.4/950-1009-firmware-raspberrypi-Add-support-for-tryonce-reboot-.patch
new file mode 100644 (file)
index 0000000..4d7a83f
--- /dev/null
@@ -0,0 +1,72 @@
+From bf41f32582df3ca5faab2cf2de15e5d4ff688822 Mon Sep 17 00:00:00 2001
+From: Tim Gover <tim.gover@raspberrypi.com>
+Date: Tue, 20 Oct 2020 11:55:37 +0100
+Subject: [PATCH] firmware: raspberrypi: Add support for tryonce
+ reboot flag
+
+Define a new mailbox (SET_REBOOT_FLAGS) which may be used to
+pass optional flags to the Raspberry Pi firmware that changes
+the behaviour of the bootloader and firmware during a reboot.
+
+Currently this just defines the 'tryboot' flag which causes
+the firmware to load tryboot.txt instead config.txt. This
+alternate configuration file can be used to specify the
+path of an alternate firmware and kernels allowing a fallback
+mechanism to be implemented for OS upgrades.
+---
+ drivers/firmware/raspberrypi.c             | 25 ++++++++++++++++++++--
+ include/soc/bcm2835/raspberrypi-firmware.h |  2 ++
+ 2 files changed, 25 insertions(+), 2 deletions(-)
+
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -190,6 +190,7 @@ static int rpi_firmware_notify_reboot(st
+ {
+       struct rpi_firmware *fw;
+       struct platform_device *pdev = g_pdev;
++      u32 reboot_flags = 0;
+       if (!pdev)
+               return 0;
+@@ -198,8 +199,28 @@ static int rpi_firmware_notify_reboot(st
+       if (!fw)
+               return 0;
+-      (void)rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT,
+-                                  0, 0);
++      // The partition id is the first parameter followed by zero or
++      // more flags separated by spaces indicating the reason for the reboot.
++      //
++      // 'tryboot': Sets a one-shot flag which is cleared upon reboot and
++      //            causes the tryboot.txt to be loaded instead of config.txt
++      //            by the bootloader and the start.elf firmware.
++      //
++      //            This is intended to allow automatic fallback to a known
++      //            good image if an OS/FW upgrade fails.
++      //
++      // N.B. The firmware mechanism for storing reboot flags may vary
++      // on different Raspberry Pi models.
++      if (data && strstr(data, " tryboot"))
++              reboot_flags |= 0x1;
++
++      // The mailbox might have been called earlier, directly via vcmailbox
++      // so only overwrite if reboot flags are passed to the reboot command.
++      if (reboot_flags)
++              (void)rpi_firmware_property(fw, RPI_FIRMWARE_SET_REBOOT_FLAGS,
++                              &reboot_flags, sizeof(reboot_flags));
++
++      (void)rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
+       return 0;
+ }
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -96,6 +96,8 @@ enum rpi_firmware_property_tag {
+       RPI_FIRMWARE_GET_POE_HAT_VAL =                        0x00030049,
+       RPI_FIRMWARE_SET_POE_HAT_VAL =                        0x00030050,
+       RPI_FIRMWARE_NOTIFY_XHCI_RESET =                      0x00030058,
++      RPI_FIRMWARE_GET_REBOOT_FLAGS =                       0x00030064,
++      RPI_FIRMWARE_SET_REBOOT_FLAGS =                       0x00038064,
+       /* Dispmanx TAGS */
+       RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE =                   0x00040001,
diff --git a/target/linux/bcm27xx/patches-5.4/950-1010-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch b/target/linux/bcm27xx/patches-5.4/950-1010-phy-broadcom-split-out-the-BCM54213PE-from-the-BCM54.patch
new file mode 100644 (file)
index 0000000..cf376b9
--- /dev/null
@@ -0,0 +1,71 @@
+From 797cf96a09d1d4ee851a3998e590f7641cfc9b9a Mon Sep 17 00:00:00 2001
+From: Jonathan Bell <jonathan@raspberrypi.org>
+Date: Tue, 14 May 2019 17:00:41 +0100
+Subject: [PATCH] phy: broadcom: split out the BCM54213PE from the
+ BCM54210E IDs
+
+The last nibble is a revision ID, and the 54213pe is a later rev
+than the 54210e. Running the 54210e setup code on a 54213pe results
+in a broken RGMII interface.
+
+Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
+---
+ drivers/net/phy/broadcom.c | 16 +++++++++++++---
+ include/linux/brcmphy.h    |  1 +
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -213,7 +213,8 @@ static void bcm54xx_adjust_rxrefclk(stru
+       /* Abort if we are using an untested phy. */
+       if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
+           BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
+-          BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
++          BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M &&
++          BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54213PE)
+               return;
+       val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
+@@ -620,13 +621,21 @@ static struct phy_driver broadcom_driver
+       .config_intr    = bcm_phy_config_intr,
+ }, {
+       .phy_id         = PHY_ID_BCM54210E,
+-      .phy_id_mask    = 0xfffffff0,
++      .phy_id_mask    = 0xffffffff,
+       .name           = "Broadcom BCM54210E",
+       /* PHY_GBIT_FEATURES */
+       .config_init    = bcm54xx_config_init,
+       .ack_interrupt  = bcm_phy_ack_intr,
+       .config_intr    = bcm_phy_config_intr,
+ }, {
++      .phy_id         = PHY_ID_BCM54213PE,
++      .phy_id_mask    = 0xffffffff,
++      .name           = "Broadcom BCM54213PE",
++      /* PHY_GBIT_FEATURES */
++      .config_init    = bcm54xx_config_init,
++      .ack_interrupt  = bcm_phy_ack_intr,
++      .config_intr    = bcm_phy_config_intr,
++}, {
+       .phy_id         = PHY_ID_BCM5461,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM5461",
+@@ -753,7 +762,8 @@ module_phy_driver(broadcom_drivers);
+ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
+       { PHY_ID_BCM5411, 0xfffffff0 },
+       { PHY_ID_BCM5421, 0xfffffff0 },
+-      { PHY_ID_BCM54210E, 0xfffffff0 },
++      { PHY_ID_BCM54210E, 0xffffffff },
++      { PHY_ID_BCM54213PE, 0xffffffff },
+       { PHY_ID_BCM5461, 0xfffffff0 },
+       { PHY_ID_BCM54612E, 0xfffffff0 },
+       { PHY_ID_BCM54616S, 0xfffffff0 },
+--- a/include/linux/brcmphy.h
++++ b/include/linux/brcmphy.h
+@@ -20,6 +20,7 @@
+ #define PHY_ID_BCM5411                        0x00206070
+ #define PHY_ID_BCM5421                        0x002060e0
+ #define PHY_ID_BCM54210E              0x600d84a0
++#define PHY_ID_BCM54213PE             0x600d84a2
+ #define PHY_ID_BCM5464                        0x002060b0
+ #define PHY_ID_BCM5461                        0x002060c0
+ #define PHY_ID_BCM54612E              0x03625e60
diff --git a/target/linux/bcm27xx/patches-5.4/950-1011-phy-broadcom-Add-bcm54213pe-configuration.patch b/target/linux/bcm27xx/patches-5.4/950-1011-phy-broadcom-Add-bcm54213pe-configuration.patch
new file mode 100644 (file)
index 0000000..d4f6c24
--- /dev/null
@@ -0,0 +1,35 @@
+From 9c08f4ff9f8f9e56011395dc064100ff6f139bdc Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 29 Oct 2020 14:10:56 +0000
+Subject: [PATCH] phy: broadcom: Add bcm54213pe configuration
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/net/phy/broadcom.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -43,6 +43,11 @@ static int bcm54210e_config_init(struct
+       return 0;
+ }
++static int bcm54213pe_config_init(struct phy_device *phydev)
++{
++      return bcm54210e_config_init(phydev);
++}
++
+ static int bcm54612e_config_init(struct phy_device *phydev)
+ {
+       int reg;
+@@ -304,6 +309,10 @@ static int bcm54xx_config_init(struct ph
+               err = bcm54210e_config_init(phydev);
+               if (err)
+                       return err;
++      } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54213PE) {
++              err = bcm54213pe_config_init(phydev);
++              if (err)
++                      return err;
+       } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
+               err = bcm54612e_config_init(phydev);
+               if (err)
diff --git a/target/linux/bcm27xx/patches-5.4/950-1012-Allo-boss2-driver.patch b/target/linux/bcm27xx/patches-5.4/950-1012-Allo-boss2-driver.patch
new file mode 100644 (file)
index 0000000..aacbc7d
--- /dev/null
@@ -0,0 +1,1185 @@
+From 51ce8712f4633484615b9982dc48038b3b86e235 Mon Sep 17 00:00:00 2001
+From: Sudeep <sudeepkumar@cem-solutions.net>
+Date: Fri, 23 Oct 2020 15:47:17 +0530
+Subject: [PATCH] Allo boss2 driver
+
+Signed-off-by: Sudeep <sudeepkumar@cem-solutions.net>
+---
+ sound/soc/bcm/Kconfig          |    9 +
+ sound/soc/bcm/Makefile         |    2 +
+ sound/soc/bcm/allo-boss2-dac.c | 1133 ++++++++++++++++++++++++++++++++
+ 3 files changed, 1144 insertions(+)
+ create mode 100644 sound/soc/bcm/allo-boss2-dac.c
+
+--- a/sound/soc/bcm/Kconfig
++++ b/sound/soc/bcm/Kconfig
+@@ -258,6 +258,15 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC
+       help
+         Say Y or M if you want to add support for Allo Boss DAC.
++config SND_BCM2708_SOC_ALLO_BOSS2_DAC
++      tristate "Support for Allo Boss2 DAC"
++      depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
++      depends on I2C
++      select REGMAP_I2C
++      select SND_AUDIO_GRAPH_CARD
++      help
++        Say Y or M if you want to add support for Allo Boss2 DAC.
++
+ config SND_BCM2708_SOC_ALLO_DIGIONE
+       tristate "Support for Allo DigiOne"
+       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+--- a/sound/soc/bcm/Makefile
++++ b/sound/soc/bcm/Makefile
+@@ -33,6 +33,7 @@ snd-soc-digidac1-soundcard-objs := digid
+ snd-soc-dionaudio-loco-objs := dionaudio_loco.o
+ snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o
+ snd-soc-allo-boss-dac-objs := allo-boss-dac.o
++snd-soc-allo-boss2-dac-objs := allo-boss2-dac.o
+ snd-soc-allo-piano-dac-objs := allo-piano-dac.o
+ snd-soc-allo-piano-dac-plus-objs := allo-piano-dac-plus.o
+ snd-soc-allo-katana-codec-objs := allo-katana-codec.o
+@@ -63,6 +64,7 @@ obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) +=
+ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o
+ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o
+ obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += snd-soc-allo-boss-dac.o
++obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS2_DAC) += snd-soc-allo-boss2-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
+ obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS) += snd-soc-allo-piano-dac-plus.o
+ obj-$(CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC) += snd-soc-allo-katana-codec.o
+--- /dev/null
++++ b/sound/soc/bcm/allo-boss2-dac.c
+@@ -0,0 +1,1133 @@
++/*
++ * Driver for the ALLO KATANA CODEC
++ *
++ * Author: Jaikumar <sudeepkumar@cem-solutions.net>
++ *            Copyright 2018
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/i2c.h>
++#include <linux/of_device.h>
++#include <linux/regmap.h>
++#include <linux/slab.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++#include <sound/initval.h>
++#include <sound/tlv.h>
++#include <linux/of_gpio.h>
++#include <linux/regulator/consumer.h>
++#include <linux/pm_runtime.h>
++#include <linux/of_irq.h>
++#include <linux/completion.h>
++#include <linux/mutex.h>
++#include <linux/workqueue.h>
++#include <sound/jack.h>
++
++#include "../codecs/cs43130.h"
++
++#include <linux/clk.h>
++#include <linux/gcd.h>
++#define DEBUG
++
++#define CS43130_DSD_EN_MASK             0x10
++#define CS43130_PDN_DONE_INT_MASK        0x00
++
++static struct gpio_desc *snd_allo_clk44gpio;
++static struct gpio_desc *snd_allo_clk48gpio;
++
++struct  cs43130_priv {
++      struct snd_soc_component        *component;
++      struct regmap                   *regmap;
++      struct regulator_bulk_data      supplies[CS43130_NUM_SUPPLIES];
++      struct gpio_desc                *reset_gpio;
++      unsigned int                    dev_id; /* codec device ID */
++      int                             xtal_ibias;
++      /* shared by both DAIs */
++      struct mutex                    clk_mutex;
++      int                             clk_req;
++      bool                            pll_bypass;
++      struct completion               xtal_rdy;
++      struct completion               pll_rdy;
++      unsigned int                    mclk;
++      unsigned int                    mclk_int;
++      int                             mclk_int_src;
++
++      /* DAI specific */
++      struct cs43130_dai              dais[CS43130_DAI_ID_MAX];
++
++      /* HP load specific */
++      bool                            dc_meas;
++      bool                            ac_meas;
++      bool                            hpload_done;
++      struct completion               hpload_evt;
++      unsigned int                    hpload_stat;
++      u16                             hpload_dc[2];
++      u16                             dc_threshold[CS43130_DC_THRESHOLD];
++      u16                             ac_freq[CS43130_AC_FREQ];
++      u16                             hpload_ac[CS43130_AC_FREQ][2];
++      struct workqueue_struct         *wq;
++      struct work_struct              work;
++      struct snd_soc_jack             jack;
++};
++
++static const struct reg_default cs43130_reg_defaults[] = {
++      {CS43130_SYS_CLK_CTL_1, 0x06},
++      {CS43130_SP_SRATE, 0x01},
++      {CS43130_SP_BITSIZE, 0x05},
++      {CS43130_PAD_INT_CFG, 0x03},
++      {CS43130_PWDN_CTL, 0xFE},
++      {CS43130_CRYSTAL_SET, 0x04},
++      {CS43130_PLL_SET_1, 0x00},
++      {CS43130_PLL_SET_2, 0x00},
++      {CS43130_PLL_SET_3, 0x00},
++      {CS43130_PLL_SET_4, 0x00},
++      {CS43130_PLL_SET_5, 0x40},
++      {CS43130_PLL_SET_6, 0x10},
++      {CS43130_PLL_SET_7, 0x80},
++      {CS43130_PLL_SET_8, 0x03},
++      {CS43130_PLL_SET_9, 0x02},
++      {CS43130_PLL_SET_10, 0x02},
++      {CS43130_CLKOUT_CTL, 0x00},
++      {CS43130_ASP_NUM_1, 0x01},
++      {CS43130_ASP_NUM_2, 0x00},
++      {CS43130_ASP_DEN_1, 0x08},
++      {CS43130_ASP_DEN_2, 0x00},
++      {CS43130_ASP_LRCK_HI_TIME_1, 0x1F},
++      {CS43130_ASP_LRCK_HI_TIME_2, 0x00},
++      {CS43130_ASP_LRCK_PERIOD_1, 0x3F},
++      {CS43130_ASP_LRCK_PERIOD_2, 0x00},
++      {CS43130_ASP_CLOCK_CONF, 0x0C},
++      {CS43130_ASP_FRAME_CONF, 0x0A},
++      {CS43130_XSP_NUM_1, 0x01},
++      {CS43130_XSP_NUM_2, 0x00},
++      {CS43130_XSP_DEN_1, 0x02},
++      {CS43130_XSP_DEN_2, 0x00},
++      {CS43130_XSP_LRCK_HI_TIME_1, 0x1F},
++      {CS43130_XSP_LRCK_HI_TIME_2, 0x00},
++      {CS43130_XSP_LRCK_PERIOD_1, 0x3F},
++      {CS43130_XSP_LRCK_PERIOD_2, 0x00},
++      {CS43130_XSP_CLOCK_CONF, 0x0C},
++      {CS43130_XSP_FRAME_CONF, 0x0A},
++      {CS43130_ASP_CH_1_LOC, 0x00},
++      {CS43130_ASP_CH_2_LOC, 0x00},
++      {CS43130_ASP_CH_1_SZ_EN, 0x06},
++      {CS43130_ASP_CH_2_SZ_EN, 0x0E},
++      {CS43130_XSP_CH_1_LOC, 0x00},
++      {CS43130_XSP_CH_2_LOC, 0x00},
++      {CS43130_XSP_CH_1_SZ_EN, 0x06},
++      {CS43130_XSP_CH_2_SZ_EN, 0x0E},
++      {CS43130_DSD_VOL_B, 0x78},
++      {CS43130_DSD_VOL_A, 0x78},
++      {CS43130_DSD_PATH_CTL_1, 0xA8},
++      {CS43130_DSD_INT_CFG, 0x00},
++      {CS43130_DSD_PATH_CTL_2, 0x02},
++      {CS43130_DSD_PCM_MIX_CTL, 0x00},
++      {CS43130_DSD_PATH_CTL_3, 0x40},
++      {CS43130_HP_OUT_CTL_1, 0x30},
++      {CS43130_PCM_FILT_OPT, 0x02},
++      {CS43130_PCM_VOL_B, 0x78},
++      {CS43130_PCM_VOL_A, 0x78},
++      {CS43130_PCM_PATH_CTL_1, 0xA8},
++      {CS43130_PCM_PATH_CTL_2, 0x00},
++      {CS43130_CLASS_H_CTL, 0x1E},
++      {CS43130_HP_DETECT, 0x04},
++      {CS43130_HP_LOAD_1, 0x00},
++      {CS43130_HP_MEAS_LOAD_1, 0x00},
++      {CS43130_HP_MEAS_LOAD_2, 0x00},
++      {CS43130_INT_MASK_1, 0xFF},
++      {CS43130_INT_MASK_2, 0xFF},
++      {CS43130_INT_MASK_3, 0xFF},
++      {CS43130_INT_MASK_4, 0xFF},
++      {CS43130_INT_MASK_5, 0xFF},
++};
++static bool cs43130_volatile_register(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
++      case CS43130_HP_DC_STAT_1 ... CS43130_HP_DC_STAT_2:
++      case CS43130_HP_AC_STAT_1 ... CS43130_HP_AC_STAT_2:
++              return true;
++      default:
++              return false;
++      }
++}
++
++static const char * const pcm_spd_texts[] = {
++      "Fast",
++      "Slow",
++};
++
++static SOC_ENUM_SINGLE_DECL(pcm_spd_enum, CS43130_PCM_FILT_OPT, 7,
++                      pcm_spd_texts);
++
++static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
++
++static const struct snd_kcontrol_new cs43130_controls[] = {
++      SOC_DOUBLE_R_TLV("Master Playback Volume", CS43130_PCM_VOL_B,
++                      CS43130_PCM_VOL_A, 0, 255, 1, master_tlv),
++      SOC_DOUBLE("Master Playback Switch", CS43130_PCM_PATH_CTL_1,
++                      0, 1, 1, 1),
++      SOC_DOUBLE_R_TLV("Digital Playback Volume", CS43130_DSD_VOL_B,
++                      CS43130_DSD_VOL_A, 0, 255, 1, master_tlv),
++      SOC_DOUBLE("Digital Playback Switch", CS43130_DSD_PATH_CTL_1,
++                      0, 1, 1, 1),
++      SOC_SINGLE("HV_Enable", CS43130_HP_OUT_CTL_1, 0, 1, 0),
++      SOC_ENUM("PCM Filter Speed", pcm_spd_enum),
++      SOC_SINGLE("PCM Phase Compensation", CS43130_PCM_FILT_OPT, 6, 1, 0),
++      SOC_SINGLE("PCM Nonoversample Emulate", CS43130_PCM_FILT_OPT, 5, 1, 0),
++      SOC_SINGLE("PCM High-pass Filter", CS43130_PCM_FILT_OPT, 1, 1, 0),
++      SOC_SINGLE("PCM De-emphasis Filter", CS43130_PCM_FILT_OPT, 0, 1, 0),
++};
++
++static bool cs43130_readable_register(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case CS43130_DEVID_AB ... CS43130_SYS_CLK_CTL_1:
++      case CS43130_SP_SRATE ... CS43130_PAD_INT_CFG:
++      case CS43130_PWDN_CTL:
++      case CS43130_CRYSTAL_SET:
++      case CS43130_PLL_SET_1 ... CS43130_PLL_SET_5:
++      case CS43130_PLL_SET_6:
++      case CS43130_PLL_SET_7:
++      case CS43130_PLL_SET_8:
++      case CS43130_PLL_SET_9:
++      case CS43130_PLL_SET_10:
++      case CS43130_CLKOUT_CTL:
++      case CS43130_ASP_NUM_1 ... CS43130_ASP_FRAME_CONF:
++      case CS43130_XSP_NUM_1 ... CS43130_XSP_FRAME_CONF:
++      case CS43130_ASP_CH_1_LOC:
++      case CS43130_ASP_CH_2_LOC:
++      case CS43130_ASP_CH_1_SZ_EN:
++      case CS43130_ASP_CH_2_SZ_EN:
++      case CS43130_XSP_CH_1_LOC:
++      case CS43130_XSP_CH_2_LOC:
++      case CS43130_XSP_CH_1_SZ_EN:
++      case CS43130_XSP_CH_2_SZ_EN:
++      case CS43130_DSD_VOL_B ... CS43130_DSD_PATH_CTL_3:
++      case CS43130_HP_OUT_CTL_1:
++      case CS43130_PCM_FILT_OPT ... CS43130_PCM_PATH_CTL_2:
++      case CS43130_CLASS_H_CTL:
++      case CS43130_HP_DETECT:
++      case CS43130_HP_STATUS:
++      case CS43130_HP_LOAD_1:
++      case CS43130_HP_MEAS_LOAD_1:
++      case CS43130_HP_MEAS_LOAD_2:
++      case CS43130_HP_DC_STAT_1:
++      case CS43130_HP_DC_STAT_2:
++      case CS43130_HP_AC_STAT_1:
++      case CS43130_HP_AC_STAT_2:
++      case CS43130_HP_LOAD_STAT:
++      case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
++      case CS43130_INT_MASK_1 ... CS43130_INT_MASK_5:
++              return true;
++      default:
++              return false;
++      }
++}
++static bool cs43130_precious_register(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
++              return true;
++      default:
++              return false;
++      }
++}
++static int cs43130_pcm_pdn(struct snd_soc_component *component)
++{
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++      int ret;
++      unsigned int reg, pdn_int;
++
++      regmap_write(cs43130->regmap, CS43130_DSD_PATH_CTL_2, 0x02);
++      regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
++                      CS43130_PDN_DONE_INT_MASK, 0);
++      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                      CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT);
++      usleep_range(10, 50);
++      ret = regmap_read(cs43130->regmap, CS43130_INT_STATUS_1, &reg);
++      pdn_int = reg & 0xFE;
++      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                      CS43130_PDN_ASP_MASK, 1 << CS43130_PDN_ASP_SHIFT);
++      return 0;
++
++}
++static int cs43130_pwr_up_asp_dac(struct snd_soc_component *component)
++{
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++
++      regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
++                      CS43130_ASP_3ST_MASK, 0);
++      regmap_write(cs43130->regmap, CS43130_DXD1, 0x99);
++      regmap_write(cs43130->regmap, CS43130_DXD13, 0x20);
++      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                      CS43130_PDN_ASP_MASK, 0);
++      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                      CS43130_PDN_HP_MASK, 0);
++      usleep_range(10000, 12000);
++      regmap_write(cs43130->regmap, CS43130_DXD1, 0x00);
++      regmap_write(cs43130->regmap, CS43130_DXD13, 0x00);
++      return 0;
++}
++static int cs43130_change_clksrc(struct snd_soc_component *component,
++                              enum cs43130_mclk_src_sel src)
++{
++      int ret;
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++      int mclk_int_decoded;
++
++      if (src == cs43130->mclk_int_src) {
++              /* clk source has not changed */
++              return 0;
++      }
++      switch (cs43130->mclk_int) {
++      case CS43130_MCLK_22M:
++              mclk_int_decoded = CS43130_MCLK_22P5;
++              break;
++      case CS43130_MCLK_24M:
++              mclk_int_decoded = CS43130_MCLK_24P5;
++              break;
++      default:
++              dev_err(component->dev, "Invalid MCLK INT freq: %u\n",
++                      cs43130->mclk_int);
++              return -EINVAL;
++      }
++
++      switch (src) {
++      case CS43130_MCLK_SRC_EXT:
++              cs43130->pll_bypass = true;
++              cs43130->mclk_int_src = CS43130_MCLK_SRC_EXT;
++              if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {
++                      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                                      CS43130_PDN_XTAL_MASK,
++                                      1 << CS43130_PDN_XTAL_SHIFT);
++              } else {
++                      reinit_completion(&cs43130->xtal_rdy);
++                      regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
++                                      CS43130_XTAL_RDY_INT_MASK, 0);
++                      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                                      CS43130_PDN_XTAL_MASK, 0);
++                      ret = wait_for_completion_timeout(&cs43130->xtal_rdy,
++                                      msecs_to_jiffies(100));
++                      regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
++                                      CS43130_XTAL_RDY_INT_MASK,
++                                      1 << CS43130_XTAL_RDY_INT_SHIFT);
++                      if (ret == 0) {
++                              dev_err(component->dev, "Timeout waiting for XTAL_READY interrupt\n");
++                              return -ETIMEDOUT;
++                      }
++              }
++      regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
++                              CS43130_MCLK_SRC_SEL_MASK,
++                              src << CS43130_MCLK_SRC_SEL_SHIFT);
++      regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
++                              CS43130_MCLK_INT_MASK,
++                              mclk_int_decoded << CS43130_MCLK_INT_SHIFT);
++      usleep_range(150, 200);
++      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                              CS43130_PDN_PLL_MASK,
++                              1 << CS43130_PDN_PLL_SHIFT);
++      break;
++      case CS43130_MCLK_SRC_RCO:
++              cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
++
++              regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
++                              CS43130_MCLK_SRC_SEL_MASK,
++                              src << CS43130_MCLK_SRC_SEL_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
++                              CS43130_MCLK_INT_MASK,
++                              CS43130_MCLK_22P5 << CS43130_MCLK_INT_SHIFT);
++              usleep_range(150, 200);
++              regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                              CS43130_PDN_XTAL_MASK,
++                              1 << CS43130_PDN_XTAL_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                              CS43130_PDN_PLL_MASK,
++                              1 << CS43130_PDN_PLL_SHIFT);
++      break;
++      default:
++              dev_err(component->dev, "Invalid MCLK source value\n");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++static const struct cs43130_bitwidth_map cs43130_bitwidth_table[] = {
++      {8,     CS43130_SP_BIT_SIZE_8,  CS43130_CH_BIT_SIZE_8},
++      {16,    CS43130_SP_BIT_SIZE_16, CS43130_CH_BIT_SIZE_16},
++      {24,    CS43130_SP_BIT_SIZE_24, CS43130_CH_BIT_SIZE_24},
++      {32,    CS43130_SP_BIT_SIZE_32, CS43130_CH_BIT_SIZE_32},
++};
++
++static const struct cs43130_bitwidth_map *cs43130_get_bitwidth_table(
++                                      unsigned int bitwidth)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(cs43130_bitwidth_table); i++) {
++              if (cs43130_bitwidth_table[i].bitwidth == bitwidth)
++                      return &cs43130_bitwidth_table[i];
++      }
++
++      return NULL;
++}
++static int cs43130_set_bitwidth(int dai_id, unsigned int bitwidth_dai,
++                              struct regmap *regmap)
++{
++      const struct cs43130_bitwidth_map *bw_map;
++
++      bw_map = cs43130_get_bitwidth_table(bitwidth_dai);
++      if (!bw_map)
++              return -EINVAL;
++
++      switch (dai_id) {
++      case CS43130_ASP_PCM_DAI:
++      case CS43130_ASP_DOP_DAI:
++              regmap_update_bits(regmap, CS43130_ASP_CH_1_SZ_EN,
++                              CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
++              regmap_update_bits(regmap, CS43130_ASP_CH_2_SZ_EN,
++                              CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
++              regmap_update_bits(regmap, CS43130_SP_BITSIZE,
++                              CS43130_ASP_BITSIZE_MASK, bw_map->sp_bit);
++              break;
++      case CS43130_XSP_DOP_DAI:
++              regmap_update_bits(regmap, CS43130_XSP_CH_1_SZ_EN,
++                              CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
++              regmap_update_bits(regmap, CS43130_XSP_CH_2_SZ_EN,
++                              CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
++              regmap_update_bits(regmap, CS43130_SP_BITSIZE,
++                              CS43130_XSP_BITSIZE_MASK, bw_map->sp_bit <<
++                              CS43130_XSP_BITSIZE_SHIFT);
++      break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++static const struct cs43130_rate_map cs43130_rate_table[] = {
++      {32000,         CS43130_ASP_SPRATE_32K},
++      {44100,         CS43130_ASP_SPRATE_44_1K},
++      {48000,         CS43130_ASP_SPRATE_48K},
++      {88200,         CS43130_ASP_SPRATE_88_2K},
++      {96000,         CS43130_ASP_SPRATE_96K},
++      {176400,        CS43130_ASP_SPRATE_176_4K},
++      {192000,        CS43130_ASP_SPRATE_192K},
++      {352800,        CS43130_ASP_SPRATE_352_8K},
++      {384000,        CS43130_ASP_SPRATE_384K},
++};
++
++static const struct cs43130_rate_map *cs43130_get_rate_table(int fs)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(cs43130_rate_table); i++) {
++              if (cs43130_rate_table[i].fs == fs)
++                      return &cs43130_rate_table[i];
++      }
++
++      return NULL;
++}
++
++static const struct cs43130_clk_gen *cs43130_get_clk_gen(int mclk_int, int fs,
++      const struct cs43130_clk_gen *clk_gen_table, int len_clk_gen_table)
++{
++      int i;
++
++      for (i = 0; i < len_clk_gen_table; i++) {
++              if (clk_gen_table[i].mclk_int == mclk_int &&
++                                      clk_gen_table[i].fs == fs)
++                      return &clk_gen_table[i];
++      }
++      return NULL;
++}
++
++static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,
++                              struct snd_pcm_hw_params *params,
++                              struct cs43130_priv *cs43130)
++{
++      u16 frm_size;
++      u16 hi_size;
++      u8 frm_delay;
++      u8 frm_phase;
++      u8 frm_data;
++      u8 sclk_edge;
++      u8 lrck_edge;
++      u8 clk_data;
++      u8 loc_ch1;
++      u8 loc_ch2;
++      u8 dai_mode_val;
++      const struct cs43130_clk_gen *clk_gen;
++
++      switch (cs43130->dais[dai_id].dai_format) {
++      case SND_SOC_DAIFMT_I2S:
++              hi_size = bitwidth_sclk;
++              frm_delay = 2;
++              frm_phase = 0;
++              break;
++      case SND_SOC_DAIFMT_LEFT_J:
++              hi_size = bitwidth_sclk;
++              frm_delay = 2;
++              frm_phase = 1;
++              break;
++      case SND_SOC_DAIFMT_DSP_A:
++              hi_size = 1;
++              frm_delay = 2;
++              frm_phase = 1;
++              break;
++      case SND_SOC_DAIFMT_DSP_B:
++              hi_size = 1;
++              frm_delay = 0;
++              frm_phase = 1;
++              break;
++      default:
++              return -EINVAL;
++      }
++      switch (cs43130->dais[dai_id].dai_mode) {
++      case SND_SOC_DAIFMT_CBS_CFS:
++              dai_mode_val = 0;
++              break;
++      case SND_SOC_DAIFMT_CBM_CFM:
++              dai_mode_val = 1;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      frm_size = bitwidth_sclk * params_channels(params);
++      sclk_edge = 1;
++      lrck_edge = 0;
++      loc_ch1 = 0;
++      loc_ch2 = bitwidth_sclk * (params_channels(params) - 1);
++
++      frm_data = frm_delay & CS43130_SP_FSD_MASK;
++      frm_data |= (frm_phase << CS43130_SP_STP_SHIFT) & CS43130_SP_STP_MASK;
++
++      clk_data = lrck_edge & CS43130_SP_LCPOL_IN_MASK;
++      clk_data |= (lrck_edge << CS43130_SP_LCPOL_OUT_SHIFT) &
++                      CS43130_SP_LCPOL_OUT_MASK;
++      clk_data |= (sclk_edge << CS43130_SP_SCPOL_IN_SHIFT) &
++                      CS43130_SP_SCPOL_IN_MASK;
++      clk_data |= (sclk_edge << CS43130_SP_SCPOL_OUT_SHIFT) &
++                      CS43130_SP_SCPOL_OUT_MASK;
++      clk_data |= (dai_mode_val << CS43130_SP_MODE_SHIFT) &
++                      CS43130_SP_MODE_MASK;
++      switch (dai_id) {
++      case CS43130_ASP_PCM_DAI:
++      case CS43130_ASP_DOP_DAI:
++              regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_1,
++                      CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
++                      CS43130_SP_LCPR_LSB_DATA_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_2,
++                      CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
++                      CS43130_SP_LCPR_MSB_DATA_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_1,
++                      CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
++                      CS43130_SP_LCHI_LSB_DATA_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_2,
++                      CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
++                      CS43130_SP_LCHI_MSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_ASP_FRAME_CONF, frm_data);
++              regmap_write(cs43130->regmap, CS43130_ASP_CH_1_LOC, loc_ch1);
++              regmap_write(cs43130->regmap, CS43130_ASP_CH_2_LOC, loc_ch2);
++              regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_1_SZ_EN,
++                      CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_2_SZ_EN,
++                      CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_ASP_CLOCK_CONF, clk_data);
++              break;
++      case CS43130_XSP_DOP_DAI:
++              regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_1,
++                      CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
++                      CS43130_SP_LCPR_LSB_DATA_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_2,
++                      CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
++                      CS43130_SP_LCPR_MSB_DATA_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_1,
++                      CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
++                      CS43130_SP_LCHI_LSB_DATA_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_2,
++                      CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
++                      CS43130_SP_LCHI_MSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_XSP_FRAME_CONF, frm_data);
++              regmap_write(cs43130->regmap, CS43130_XSP_CH_1_LOC, loc_ch1);
++              regmap_write(cs43130->regmap, CS43130_XSP_CH_2_LOC, loc_ch2);
++              regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_1_SZ_EN,
++                      CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_2_SZ_EN,
++                      CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_XSP_CLOCK_CONF, clk_data);
++              break;
++      default:
++              return -EINVAL;
++      }
++      switch (frm_size) {
++      case 16:
++              clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
++                                              params_rate(params),
++                                              cs43130_16_clk_gen,
++                                              ARRAY_SIZE(cs43130_16_clk_gen));
++              break;
++      case 32:
++              clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
++                                              params_rate(params),
++                                              cs43130_32_clk_gen,
++                                              ARRAY_SIZE(cs43130_32_clk_gen));
++              break;
++      case 48:
++              clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
++                                              params_rate(params),
++                                              cs43130_48_clk_gen,
++                                              ARRAY_SIZE(cs43130_48_clk_gen));
++              break;
++      case 64:
++              clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
++                                              params_rate(params),
++                                              cs43130_64_clk_gen,
++                                              ARRAY_SIZE(cs43130_64_clk_gen));
++              break;
++      default:
++              return -EINVAL;
++      }
++      if (!clk_gen)
++              return -EINVAL;
++      switch (dai_id) {
++      case CS43130_ASP_PCM_DAI:
++      case CS43130_ASP_DOP_DAI:
++              regmap_write(cs43130->regmap, CS43130_ASP_DEN_1,
++                              (clk_gen->den & CS43130_SP_M_LSB_DATA_MASK) >>
++                              CS43130_SP_M_LSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_ASP_DEN_2,
++                              (clk_gen->den & CS43130_SP_M_MSB_DATA_MASK) >>
++                              CS43130_SP_M_MSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_ASP_NUM_1,
++                              (clk_gen->num & CS43130_SP_N_LSB_DATA_MASK) >>
++                              CS43130_SP_N_LSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_ASP_NUM_2,
++                              (clk_gen->num & CS43130_SP_N_MSB_DATA_MASK) >>
++                              CS43130_SP_N_MSB_DATA_SHIFT);
++              break;
++      case CS43130_XSP_DOP_DAI:
++              regmap_write(cs43130->regmap, CS43130_XSP_DEN_1,
++                              (clk_gen->den & CS43130_SP_M_LSB_DATA_MASK) >>
++                              CS43130_SP_M_LSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_XSP_DEN_2,
++                              (clk_gen->den & CS43130_SP_M_MSB_DATA_MASK) >>
++                              CS43130_SP_M_MSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_XSP_NUM_1,
++                              (clk_gen->num & CS43130_SP_N_LSB_DATA_MASK) >>
++                              CS43130_SP_N_LSB_DATA_SHIFT);
++              regmap_write(cs43130->regmap, CS43130_XSP_NUM_2,
++                              (clk_gen->num & CS43130_SP_N_MSB_DATA_MASK) >>
++                              CS43130_SP_N_MSB_DATA_SHIFT);
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static int cs43130_hw_params(struct snd_pcm_substream *substream,
++                              struct snd_pcm_hw_params *params,
++                              struct snd_soc_dai *dai)
++{
++      struct snd_soc_component *component = dai->component;
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++      const struct cs43130_rate_map *rate_map;
++      unsigned int sclk = cs43130->dais[dai->id].sclk;
++      unsigned int bitwidth_sclk;
++      unsigned int bitwidth_dai = (unsigned int)(params_width(params));
++      unsigned int dop_rate = (unsigned int)(params_rate(params));
++      unsigned int required_clk, ret;
++      u8 dsd_speed;
++
++      cs43130->pll_bypass = true;
++      cs43130_pcm_pdn(component);
++      mutex_lock(&cs43130->clk_mutex);
++      if (!cs43130->clk_req) {
++              /* no DAI is currently using clk */
++              if (!(CS43130_MCLK_22M % params_rate(params))) {
++                      required_clk = CS43130_MCLK_22M;
++                      cs43130->mclk_int =  CS43130_MCLK_22M;
++                      gpiod_set_value_cansleep(snd_allo_clk44gpio, 1);
++                      gpiod_set_value_cansleep(snd_allo_clk48gpio, 0);
++                      usleep_range(13500, 14000);
++              } else {
++                      required_clk = CS43130_MCLK_24M;
++                      cs43130->mclk_int =  CS43130_MCLK_24M;
++                      gpiod_set_value_cansleep(snd_allo_clk48gpio, 1);
++                      gpiod_set_value_cansleep(snd_allo_clk44gpio, 0);
++                      usleep_range(13500, 14000);
++              }
++              if (cs43130->pll_bypass)
++                      cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);
++              else
++                      cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);
++      }
++
++      cs43130->clk_req++;
++      mutex_unlock(&cs43130->clk_mutex);
++
++      switch (dai->id) {
++      case CS43130_ASP_DOP_DAI:
++      case CS43130_XSP_DOP_DAI:
++              /* DoP bitwidth is always 24-bit */
++              bitwidth_dai = 24;
++              sclk = params_rate(params) * bitwidth_dai *
++                              params_channels(params);
++
++              switch (params_rate(params)) {
++              case 176400:
++                      dsd_speed = 0;
++                      break;
++              case 352800:
++                      dsd_speed = 1;
++                      break;
++              default:
++                      dev_err(component->dev, "Rate(%u) not supported\n",
++                              params_rate(params));
++                      return -EINVAL;
++              }
++
++              regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
++                                      CS43130_DSD_SPEED_MASK,
++                                      dsd_speed << CS43130_DSD_SPEED_SHIFT);
++              break;
++      case CS43130_ASP_PCM_DAI:
++              rate_map = cs43130_get_rate_table(params_rate(params));
++              if (!rate_map)
++                      return -EINVAL;
++
++              regmap_write(cs43130->regmap, CS43130_SP_SRATE, rate_map->val);
++              if ((dop_rate == 176400) && (bitwidth_dai == 24)) {
++                      dsd_speed = 0;
++                      regmap_update_bits(cs43130->regmap,
++                                      CS43130_DSD_PATH_CTL_2,
++                                      CS43130_DSD_SPEED_MASK,
++                                      dsd_speed << CS43130_DSD_SPEED_SHIFT);
++                      regmap_update_bits(cs43130->regmap,
++                                      CS43130_DSD_PATH_CTL_2,
++                                      CS43130_DSD_SRC_MASK,
++                                      CS43130_DSD_SRC_ASP <<
++                                      CS43130_DSD_SRC_SHIFT);
++                      regmap_update_bits(cs43130->regmap,
++                                      CS43130_DSD_PATH_CTL_2,
++                                      CS43130_DSD_EN_MASK, 0x01 <<
++                                      CS43130_DSD_EN_SHIFT);
++              }
++              break;
++      default:
++              dev_err(component->dev, "Invalid DAI (%d)\n", dai->id);
++              return -EINVAL;
++      }
++
++      switch (dai->id) {
++      case CS43130_ASP_DOP_DAI:
++              regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
++                              CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_ASP <<
++                              CS43130_DSD_SRC_SHIFT);
++              regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
++                              CS43130_DSD_EN_MASK, 0x01 <<
++                              CS43130_DSD_EN_SHIFT);
++              break;
++      case CS43130_XSP_DOP_DAI:
++              regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
++                              CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_XSP <<
++                              CS43130_DSD_SRC_SHIFT);
++              break;
++      }
++      if (!sclk && cs43130->dais[dai->id].dai_mode ==
++                                              SND_SOC_DAIFMT_CBM_CFM) {
++              /* Calculate SCLK in master mode if unassigned */
++              sclk = params_rate(params) * bitwidth_dai *
++                              params_channels(params);
++      }
++      if (!sclk) {
++              /* at this point, SCLK must be set */
++              dev_err(component->dev, "SCLK freq is not set\n");
++              return -EINVAL;
++      }
++
++      bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params);
++      if (bitwidth_sclk < bitwidth_dai) {
++              dev_err(component->dev, "Format not supported: SCLK freq is too low\n");
++              return -EINVAL;
++      }
++
++      dev_dbg(component->dev,
++              "sclk = %u, fs = %d, bitwidth_dai = %u\n",
++              sclk, params_rate(params), bitwidth_dai);
++
++      dev_dbg(component->dev,
++              "bitwidth_sclk = %u, num_ch = %u\n",
++              bitwidth_sclk, params_channels(params));
++
++      cs43130_set_bitwidth(dai->id, bitwidth_dai, cs43130->regmap);
++      cs43130_set_sp_fmt(dai->id, bitwidth_sclk, params, cs43130);
++      ret = cs43130_pwr_up_asp_dac(component);
++      return 0;
++}
++
++static int cs43130_hw_free(struct snd_pcm_substream *substream,
++                                      struct snd_soc_dai *dai)
++{
++      struct snd_soc_component *component = dai->component;
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++
++      mutex_lock(&cs43130->clk_mutex);
++      cs43130->clk_req--;
++      if (!cs43130->clk_req) {
++              /* no DAI is currently using clk */
++              cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);
++              cs43130_pcm_pdn(component);
++      }
++      mutex_unlock(&cs43130->clk_mutex);
++
++      return 0;
++}
++
++static const unsigned int cs43130_asp_src_rates[] = {
++      32000, 44100, 48000, 88200, 96000, 176400, 192000
++};
++
++static const struct snd_pcm_hw_constraint_list cs43130_asp_constraints = {
++      .count  = ARRAY_SIZE(cs43130_asp_src_rates),
++      .list   = cs43130_asp_src_rates,
++};
++
++static int cs43130_pcm_startup(struct snd_pcm_substream *substream,
++                                      struct snd_soc_dai *dai)
++{
++      return snd_pcm_hw_constraint_list(substream->runtime, 0,
++                                      SNDRV_PCM_HW_PARAM_RATE,
++                                      &cs43130_asp_constraints);
++}
++
++static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
++{
++      struct snd_soc_component *component = codec_dai->component;
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++
++      switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++      case SND_SOC_DAIFMT_CBS_CFS:
++              cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;
++              break;
++      case SND_SOC_DAIFMT_CBM_CFM:
++              cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;
++              break;
++      default:
++              dev_err(component->dev, "unsupported mode\n");
++              return -EINVAL;
++      }
++
++      switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++      case SND_SOC_DAIFMT_I2S:
++              cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_I2S;
++              break;
++      case SND_SOC_DAIFMT_LEFT_J:
++              cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_LEFT_J;
++              break;
++      default:
++              dev_err(component->dev,
++                      "unsupported audio format\n");
++              return -EINVAL;
++      }
++
++      dev_dbg(component->dev, "dai_id = %d,  dai_mode = %u, dai_format = %u\n",
++                      codec_dai->id,
++                      cs43130->dais[codec_dai->id].dai_mode,
++                      cs43130->dais[codec_dai->id].dai_format);
++
++      return 0;
++}
++
++static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai,
++                                      int clk_id, unsigned int freq, int dir)
++{
++      struct snd_soc_component *component = codec_dai->component;
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++
++      cs43130->dais[codec_dai->id].sclk = freq;
++      dev_dbg(component->dev, "dai_id = %d,  sclk = %u\n", codec_dai->id,
++                              cs43130->dais[codec_dai->id].sclk);
++
++      return 0;
++}
++
++static int cs43130_component_set_sysclk(struct snd_soc_component *component,
++                                      int clk_id, int source,
++                                      unsigned int freq, int dir)
++{
++      struct cs43130_priv *cs43130 =
++                              snd_soc_component_get_drvdata(component);
++
++      dev_dbg(component->dev, "clk_id = %d, source = %d, freq = %d, dir = %d\n",
++              clk_id, source, freq, dir);
++
++      switch (freq) {
++      case CS43130_MCLK_22M:
++      case CS43130_MCLK_24M:
++              cs43130->mclk = freq;
++              break;
++      default:
++              dev_err(component->dev, "Invalid MCLK INT freq: %u\n", freq);
++              return -EINVAL;
++      }
++
++      if (source == CS43130_MCLK_SRC_EXT) {
++              cs43130->pll_bypass = true;
++      } else {
++              dev_err(component->dev, "Invalid MCLK source\n");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = {
++      24,
++      43,
++      93,
++      200,
++      431,
++      928,
++      2000,
++      4309,
++      9283,
++      20000,
++};
++static const struct snd_soc_dai_ops cs43130_dai_ops = {
++      .startup        = cs43130_pcm_startup,
++      .hw_params      = cs43130_hw_params,
++      .hw_free        = cs43130_hw_free,
++      .set_sysclk     = cs43130_set_sysclk,
++      .set_fmt        = cs43130_pcm_set_fmt,
++};
++
++static struct snd_soc_dai_driver cs43130_codec_dai = {
++      .name = "allo-cs43130",
++      .playback = {
++              .stream_name = "Playback",
++              .channels_min = 2,
++              .channels_max = 2,
++              .rates = SNDRV_PCM_RATE_CONTINUOUS,
++              .rate_min = 44100,
++              .rate_max = 192000,
++              .formats = SNDRV_PCM_FMTBIT_S16_LE |
++                      SNDRV_PCM_FMTBIT_S24_LE |
++                      SNDRV_PCM_FMTBIT_S32_LE
++
++      },
++      .ops = &cs43130_dai_ops,
++};
++
++static struct snd_soc_component_driver cs43130_component_driver = {
++      .idle_bias_on           = true,
++      .controls               = cs43130_controls,
++      .num_controls           = ARRAY_SIZE(cs43130_controls),
++      .set_sysclk             = cs43130_component_set_sysclk,
++      .idle_bias_on           = 1,
++      .use_pmdown_time        = 1,
++      .endianness             = 1,
++      .non_legacy_dai_naming  = 1,
++};
++
++static const struct regmap_config cs43130_regmap = {
++      .reg_bits               = 24,
++      .pad_bits               = 8,
++      .val_bits               = 8,
++
++      .max_register           = CS43130_LASTREG,
++      .reg_defaults           = cs43130_reg_defaults,
++      .num_reg_defaults       = ARRAY_SIZE(cs43130_reg_defaults),
++      .readable_reg           = cs43130_readable_register,
++      .precious_reg           = cs43130_precious_register,
++      .volatile_reg           = cs43130_volatile_register,
++      .cache_type             = REGCACHE_RBTREE,
++      /* needed for regcache_sync */
++      .use_single_read        = true,
++      .use_single_write       = true,
++};
++
++static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
++      50,
++      120,
++};
++
++static int cs43130_handle_device_data(struct i2c_client *i2c_client,
++                                      struct cs43130_priv *cs43130)
++{
++      struct device_node *np = i2c_client->dev.of_node;
++      unsigned int val;
++      int i;
++
++      if (of_property_read_u32(np, "cirrus,xtal-ibias", &val) < 0) {
++      /* Crystal is unused. System clock is used for external MCLK */
++              cs43130->xtal_ibias = CS43130_XTAL_UNUSED;
++              return 0;
++      }
++
++      switch (val) {
++      case 1:
++              cs43130->xtal_ibias = CS43130_XTAL_IBIAS_7_5UA;
++              break;
++      case 2:
++              cs43130->xtal_ibias = CS43130_XTAL_IBIAS_12_5UA;
++              break;
++      case 3:
++              cs43130->xtal_ibias = CS43130_XTAL_IBIAS_15UA;
++              break;
++      default:
++              dev_err(&i2c_client->dev,
++                      "Invalid cirrus,xtal-ibias value: %d\n", val);
++              return -EINVAL;
++      }
++
++      cs43130->dc_meas = of_property_read_bool(np, "cirrus,dc-measure");
++      cs43130->ac_meas = of_property_read_bool(np, "cirrus,ac-measure");
++
++      if (of_property_read_u16_array(np, "cirrus,ac-freq", cs43130->ac_freq,
++                                      CS43130_AC_FREQ) < 0) {
++              for (i = 0; i < CS43130_AC_FREQ; i++)
++                      cs43130->ac_freq[i] = cs43130_ac_freq[i];
++      }
++
++      if (of_property_read_u16_array(np, "cirrus,dc-threshold",
++                                      cs43130->dc_threshold,
++                                      CS43130_DC_THRESHOLD) < 0) {
++              for (i = 0; i < CS43130_DC_THRESHOLD; i++)
++                      cs43130->dc_threshold[i] = cs43130_dc_threshold[i];
++      }
++
++      return 0;
++}
++
++
++static int allo_cs43130_component_probe(struct i2c_client *i2c,
++                           const struct i2c_device_id *id)
++{
++      struct regmap *regmap;
++      struct regmap_config config = cs43130_regmap;
++      struct device *dev = &i2c->dev;
++      struct cs43130_priv *cs43130;
++      unsigned int devid = 0;
++      unsigned int reg;
++      int ret;
++
++      regmap = devm_regmap_init_i2c(i2c, &config);
++      if (IS_ERR(regmap))
++              return PTR_ERR(regmap);
++
++      cs43130 = devm_kzalloc(dev, sizeof(struct cs43130_priv),
++                                      GFP_KERNEL);
++      if (!cs43130)
++              return -ENOMEM;
++
++      dev_set_drvdata(dev, cs43130);
++      cs43130->regmap = regmap;
++
++      if (i2c->dev.of_node) {
++              ret = cs43130_handle_device_data(i2c, cs43130);
++              if (ret != 0)
++                      return ret;
++      }
++      usleep_range(2000, 2050);
++
++      ret = regmap_read(cs43130->regmap, CS43130_DEVID_AB, &reg);
++      devid = (reg & 0xFF) << 12;
++      ret = regmap_read(cs43130->regmap, CS43130_DEVID_CD, &reg);
++      devid |= (reg & 0xFF) << 4;
++      ret = regmap_read(cs43130->regmap, CS43130_DEVID_E, &reg);
++      devid |= (reg & 0xF0) >> 4;
++      if (devid != CS43198_CHIP_ID) {
++              dev_err(dev, "Failed to read Chip or wrong Chip id: %d\n", ret);
++              return ret;
++      }
++
++      cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
++      msleep(20);
++
++      ret = snd_soc_register_component(dev, &cs43130_component_driver,
++                                  &cs43130_codec_dai, 1);
++      if (ret != 0) {
++              dev_err(dev, "failed to register codec: %d\n", ret);
++              return ret;
++      }
++      regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
++                      CS43130_ASP_3ST_MASK, 0);
++      regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
++                      CS43130_XSP_3ST_MASK, 1);
++      regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
++                      CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT);
++      msleep(20);
++      regmap_write(cs43130->regmap, CS43130_CLASS_H_CTL, 0x06);
++      snd_allo_clk44gpio = devm_gpiod_get(dev, "clock44", GPIOD_OUT_HIGH);
++      if (IS_ERR(snd_allo_clk44gpio))
++              dev_err(dev, "devm_gpiod_get() failed\n");
++
++      snd_allo_clk48gpio = devm_gpiod_get(dev, "clock48", GPIOD_OUT_LOW);
++      if (IS_ERR(snd_allo_clk48gpio))
++              dev_err(dev, "devm_gpiod_get() failed\n");
++
++      return 0;
++}
++
++static int allo_cs43130_component_remove(struct i2c_client *i2c)
++{
++      snd_soc_unregister_component(&i2c->dev);
++      return 0;
++}
++
++static const struct i2c_device_id allo_cs43130_component_id[] = {
++      { "allo-cs43198", },
++      { }
++};
++MODULE_DEVICE_TABLE(i2c, allo_cs43130_component_id);
++
++static const struct of_device_id allo_cs43130_codec_of_match[] = {
++      { .compatible = "allo,allo-cs43198", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, allo_cs43130_codec_of_match);
++
++static struct i2c_driver allo_cs43130_component_driver = {
++      .probe          = allo_cs43130_component_probe,
++      .remove         = allo_cs43130_component_remove,
++      .id_table       = allo_cs43130_component_id,
++      .driver         = {
++      .name           = "allo-cs43198",
++      .of_match_table = allo_cs43130_codec_of_match,
++      },
++};
++
++module_i2c_driver(allo_cs43130_component_driver);
++
++MODULE_DESCRIPTION("ASoC Allo Boss2 Codec Driver");
++MODULE_AUTHOR("Sudeepkumar <sudeepkumar@cem-solutions.net>");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/bcm27xx/patches-5.4/950-1013-Add-allo-boss2-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-1013-Add-allo-boss2-overlay.patch
new file mode 100644 (file)
index 0000000..97bc4a5
--- /dev/null
@@ -0,0 +1,98 @@
+From b07f4bea8e3259c30fa905b047dce73449147f58 Mon Sep 17 00:00:00 2001
+From: Sudeep <sudeepkumar@cem-solutions.net>
+Date: Fri, 23 Oct 2020 15:51:15 +0530
+Subject: [PATCH] Add allo boss2 overlay
+
+Signed-off-by: Sudeep <sudeepkumar@cem-solutions.net>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             |  6 ++
+ .../overlays/allo-boss2-dac-audio-overlay.dts | 57 +++++++++++++++++++
+ 3 files changed, 64 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/allo-boss2-dac-audio-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -14,6 +14,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       adv728x-m.dtbo \
+       akkordion-iqdacplus.dtbo \
+       allo-boss-dac-pcm512x-audio.dtbo \
++      allo-boss2-dac-audio.dtbo \
+       allo-digione.dtbo \
+       allo-katana-dac-audio.dtbo \
+       allo-piano-dac-pcm512x-audio.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -420,6 +420,12 @@ Params: 24db_digital_gain       Allow ga
+                                 slave"
++Name:   allo-boss2-dac-audio
++Info:   Configures the Allo Boss2 DAC audio card
++Load:   dtoverlay=allo-boss2-dac-audio
++Params: <None>
++
++
+ Name:   allo-digione
+ Info:   Configures the Allo Digione audio card
+ Load:   dtoverlay=allo-digione
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/allo-boss2-dac-audio-overlay.dts
+@@ -0,0 +1,57 @@
++/* * Definitions for Allo Boss2 DAC boards
++ */
++
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      #sound-dai-cells = <0>;
++                      status = "okay";
++                      cpu_port: port {
++                              cpu_endpoint: endpoint {
++                                      remote-endpoint = <&codec_endpoint>;
++                                      bitclock-master = <&codec_endpoint>;
++                                      frame-master = <&codec_endpoint>;
++                                      dai-format = "i2s";
++                              };
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++                      allo-cs43130@30 {
++                              #sound-dai-cells = <0>;
++                              compatible = "allo,allo-cs43198";
++                              clock44-gpio = <&gpio 5 0>;
++                              clock48-gpio = <&gpio 6 0>;
++                              reg = <0x30>;
++                              port {
++                                      codec_endpoint: endpoint {
++                                      remote-endpoint = <&cpu_endpoint>;
++                                      };
++                              };
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&sound>;
++              boss2_dac: __overlay__ {
++                      compatible = "audio-graph-card";
++                      label = "Allo Boss2";
++                      dais = <&cpu_port>;
++                      status = "okay";
++              };
++      };
++};
++
diff --git a/target/linux/bcm27xx/patches-5.4/950-1014-Revert-mailbox-avoid-timer-start-from-callback.patch b/target/linux/bcm27xx/patches-5.4/950-1014-Revert-mailbox-avoid-timer-start-from-callback.patch
new file mode 100644 (file)
index 0000000..849bdd1
--- /dev/null
@@ -0,0 +1,60 @@
+From 2b7fcd18b15d9cc7b2e68deb77f4e0acfa904c41 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 3 Nov 2020 10:13:48 +0000
+Subject: [PATCH] Revert "mailbox: avoid timer start from callback"
+
+This reverts commit 6dc15642c8b830d384fd3e6c9ea63144202b8932.
+
+The Pi 400 shutdown/poweroff mechanism relies on being able to set
+a GPIO on the expander in the pm_power_off handler, something that
+requires two mailbox calls - GET_GPIO_STATE and SET_GPIO_STATE. A
+recent kernel change introduces a reasonable possibility that the
+GET call doesn't completes, and bisecting led to a commit from
+October that changes the timer usage of the mailbox.
+
+My theory is that there is a race condition in the new code that breaks
+the poll timer, but that it normally goes unnoticed because subsequent
+mailbox activity wakes it up again. The power-off mailbox calls happen
+at a time when other subsystems have been shut down, so if one of them
+fails then there is nothing to allow it to recover.
+
+Revert 6dc15642 as (at least) a workaround.
+
+See: https://github.com/raspberrypi/linux/issues/3941
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/mailbox/mailbox.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -82,12 +82,9 @@ static void msg_submit(struct mbox_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);
+ }
+ static void tx_tick(struct mbox_chan *chan, int r)
+@@ -125,10 +122,11 @@ static enum hrtimer_restart txdone_hrtim
+               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/target/linux/bcm27xx/patches-5.4/950-1015-ARM-dts-Add-bcm2711-rpi-400.dts.patch b/target/linux/bcm27xx/patches-5.4/950-1015-ARM-dts-Add-bcm2711-rpi-400.dts.patch
new file mode 100644 (file)
index 0000000..444c7ae
--- /dev/null
@@ -0,0 +1,627 @@
+From 37034aa6ba14c346f67e8b99a317c45e40f0a2eb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 14 Jul 2020 14:21:33 +0100
+Subject: [PATCH] ARM: dts: Add bcm2711-rpi-400.dts
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/Makefile                    |   1 +
+ arch/arm/boot/dts/bcm2711-rpi-400.dts         | 585 ++++++++++++++++++
+ arch/arm64/boot/dts/broadcom/Makefile         |   1 +
+ .../boot/dts/broadcom/bcm2711-rpi-400.dts     |   1 +
+ 4 files changed, 588 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm2711-rpi-400.dts
+ create mode 100644 arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+       bcm2710-rpi-3-b.dtb \
+       bcm2710-rpi-3-b-plus.dtb \
+       bcm2711-rpi-4-b.dtb \
++      bcm2711-rpi-400.dtb \
+       bcm2710-rpi-cm3.dtb \
+       bcm2711-rpi-cm4.dtb
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm2711-rpi-400.dts
+@@ -0,0 +1,585 @@
++// SPDX-License-Identifier: GPL-2.0
++/dts-v1/;
++#include "bcm2711.dtsi"
++#include "bcm2835-rpi.dtsi"
++
++/ {
++      compatible = "raspberrypi,400", "brcm,bcm2711";
++      model = "Raspberry Pi 400";
++
++      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;
++              ethernet0 = &genet;
++              pcie0 = &pcie0;
++      };
++
++      leds {
++              act {
++                      gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
++              };
++
++              pwr {
++                      label = "PWR";
++                      gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++                      default-state = "keep";
++                      linux,default-trigger = "default-on";
++              };
++      };
++
++      wifi_pwrseq: wifi-pwrseq {
++              compatible = "mmc-pwrseq-simple";
++              reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
++      };
++
++      sd_io_1v8_reg: sd_io_1v8_reg {
++              compatible = "regulator-gpio";
++              regulator-name = "vdd-sd-io";
++              regulator-min-microvolt = <1800000>;
++              regulator-max-microvolt = <3300000>;
++              regulator-boot-on;
++              regulator-always-on;
++              regulator-settling-time-us = <5000>;
++              gpios = <&expgpio 4 GPIO_ACTIVE_HIGH>;
++              states = <1800000 0x1
++                        3300000 0x0>;
++              status = "okay";
++      };
++};
++
++&firmware {
++      expgpio: gpio {
++              compatible = "raspberrypi,firmware-gpio";
++              gpio-controller;
++              #gpio-cells = <2>;
++              gpio-line-names = "BT_ON",
++                                "WL_ON",
++                                "PWR_LED_OFF",
++                                "GLOBAL_RESET",
++                                "VDD_SD_IO_SEL",
++                                "CAM_GPIO",
++                                "SD_PWR_ON",
++                                "SD_OC_N";
++              status = "okay";
++      };
++};
++
++&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",
++                        "RGMII_MDIO",
++                        "RGMIO_MDC",
++                        /* Used by BT module */
++                        "CTS0",
++                        "RTS0",
++                        "TXD0",
++                        "RXD0",
++                        /* Used by Wifi */
++                        "SD1_CLK",
++                        "SD1_CMD",
++                        "SD1_DATA0",
++                        "SD1_DATA1",
++                        "SD1_DATA2",
++                        "SD1_DATA3",
++                        /* Shared with SPI flash */
++                        "PWM0_MISO",
++                        "PWM1_MOSI",
++                        "STATUS_LED_G_CLK",
++                        "SPIFLASH_CE_N",
++                        "SDA0",
++                        "SCL0",
++                        "RGMII_RXCLK",
++                        "RGMII_RXCTL",
++                        "RGMII_RXD0",
++                        "RGMII_RXD1",
++                        "RGMII_RXD2",
++                        "RGMII_RXD3",
++                        "RGMII_TXCLK",
++                        "RGMII_TXCTL",
++                        "RGMII_TXD0",
++                        "RGMII_TXD1",
++                        "RGMII_TXD2",
++                        "RGMII_TXD3";
++};
++
++&pwm1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
++      status = "okay";
++};
++
++/* SDHCI is used to control the SDIO for wireless */
++&sdhci {
++      #address-cells = <1>;
++      #size-cells = <0>;
++      pinctrl-names = "default";
++      pinctrl-0 = <&emmc_gpio34>;
++      bus-width = <4>;
++      non-removable;
++      mmc-pwrseq = <&wifi_pwrseq>;
++      status = "okay";
++
++      brcmf: wifi@1 {
++              reg = <1>;
++              compatible = "brcm,bcm4329-fmac";
++      };
++};
++
++/* EMMC2 is used to drive the SD card */
++&emmc2 {
++      vqmmc-supply = <&sd_io_1v8_reg>;
++      broken-cd;
++      status = "okay";
++};
++
++&genet {
++      phy-handle = <&phy1>;
++      phy-mode = "rgmii-rxid";
++      status = "okay";
++};
++
++&genet_mdio {
++      phy1: ethernet-phy@1 {
++              /* No PHY interrupt */
++              reg = <0x1>;
++      };
++};
++
++/* uart0 communicates with the BT module */
++&uart0 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32>;
++      uart-has-rtscts;
++      status = "okay";
++
++      bluetooth {
++              compatible = "brcm,bcm43438-bt";
++              max-speed = <2000000>;
++              shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
++      };
++};
++
++/* uart1 is mapped to the pin header */
++&uart1 {
++      pinctrl-names = "default";
++      pinctrl-0 = <&uart1_gpio14>;
++      status = "okay";
++};
++
++&vchiq {
++      interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
++};
++
++// =============================================
++// Downstream rpi- changes
++
++#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 snd_bcm2835.enable_headphones=1";
++      };
++
++      aliases {
++              serial0 = &uart1;
++              serial1 = &uart0;
++              mmc0 = &emmc2;
++              mmc1 = &mmcnr;
++              mmc2 = &sdhost;
++              /delete-property/ i2c2;
++              i2c3 = &i2c3;
++              i2c4 = &i2c4;
++              i2c5 = &i2c5;
++              i2c6 = &i2c6;
++              /delete-property/ intc;
++      };
++
++      /delete-node/ wifi-pwrseq;
++};
++
++&mmcnr {
++      pinctrl-names = "default";
++      pinctrl-0 = <&sdio_pins>;
++      bus-width = <4>;
++      status = "okay";
++};
++
++&uart0 {
++      pinctrl-0 = <&uart0_pins &bt_pins>;
++      status = "okay";
++};
++
++&uart1 {
++      pinctrl-0 = <&uart1_pins>;
++};
++
++&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 = <BCM2835_FSEL_ALT0>;
++      };
++
++      spi0_cs_pins: spi0_cs_pins {
++              brcm,pins = <8 7>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi3_pins: spi3_pins {
++              brcm,pins = <1 2 3>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi3_cs_pins: spi3_cs_pins {
++              brcm,pins = <0 24>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi4_pins: spi4_pins {
++              brcm,pins = <5 6 7>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi4_cs_pins: spi4_cs_pins {
++              brcm,pins = <4 25>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi5_pins: spi5_pins {
++              brcm,pins = <13 14 15>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi5_cs_pins: spi5_cs_pins {
++              brcm,pins = <12 26>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      spi6_pins: spi6_pins {
++              brcm,pins = <19 20 21>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++      };
++
++      spi6_cs_pins: spi6_cs_pins {
++              brcm,pins = <18 27>;
++              brcm,function = <BCM2835_FSEL_GPIO_OUT>;
++      };
++
++      i2c0_pins: i2c0 {
++              brcm,pins = <0 1>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c1_pins: i2c1 {
++              brcm,pins = <2 3>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c3_pins: i2c3 {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c4_pins: i2c4 {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c5_pins: i2c5 {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2c6_pins: i2c6 {
++              brcm,pins = <22 23>;
++              brcm,function = <BCM2835_FSEL_ALT5>;
++              brcm,pull = <BCM2835_PUD_UP>;
++      };
++
++      i2s_pins: i2s {
++              brcm,pins = <18 19 20 21>;
++              brcm,function = <BCM2835_FSEL_ALT0>;
++      };
++
++      sdio_pins: sdio_pins {
++              brcm,pins =     <34 35 36 37 38 39>;
++              brcm,function = <BCM2835_FSEL_ALT3>; // alt3 = SD1
++              brcm,pull =     <0 2 2 2 2 2>;
++      };
++
++      bt_pins: bt_pins {
++              brcm,pins = "-"; // non-empty to keep btuart happy, //4 = 0
++                               // to fool pinctrl
++              brcm,function = <0>;
++              brcm,pull = <2>;
++      };
++
++      uart0_pins: uart0_pins {
++              brcm,pins = <32 33>;
++              brcm,function = <BCM2835_FSEL_ALT3>;
++              brcm,pull = <0 2>;
++      };
++
++      uart1_pins: uart1_pins {
++              brcm,pins;
++              brcm,function;
++              brcm,pull;
++      };
++
++      uart2_pins: uart2_pins {
++              brcm,pins = <0 1>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <0 2>;
++      };
++
++      uart3_pins: uart3_pins {
++              brcm,pins = <4 5>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <0 2>;
++      };
++
++      uart4_pins: uart4_pins {
++              brcm,pins = <8 9>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              brcm,pull = <0 2>;
++      };
++
++      uart5_pins: uart5_pins {
++              brcm,pins = <12 13>;
++              brcm,function = <BCM2835_FSEL_ALT4>;
++              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>;
++};
++
++/ {
++      __overrides__ {
++              /delete-property/ i2c2_baudrate;
++              /delete-property/ i2c2_iknowwhatimdoing;
++      };
++};
++
++&firmwarekms {
++      compatible = "raspberrypi,rpi-firmware-kms-2711";
++};
++
++// =============================================
++// Board specific stuff here
++
++/ {
++      sd_vcc_reg: sd_vcc_reg {
++              compatible = "regulator-fixed";
++              regulator-name = "vcc-sd";
++              regulator-min-microvolt = <3300000>;
++              regulator-max-microvolt = <3300000>;
++              regulator-boot-on;
++              enable-active-high;
++              gpio = <&expgpio 6 GPIO_ACTIVE_HIGH>;
++      };
++
++      power_ctrl: power_ctrl {
++              compatible = "gpio-poweroff";
++              gpios = <&expgpio 5 0>;
++              force;
++      };
++};
++
++&sdhost {
++      status = "disabled";
++};
++
++&emmc2 {
++      vmmc-supply = <&sd_vcc_reg>;
++};
++
++&phy1 {
++      led-modes = <0x00 0x08>; /* link/activity link */
++};
++
++&gpio {
++      audio_pins: audio_pins {
++              brcm,pins = <40 41>;
++              brcm,function = <4>;
++      };
++};
++
++&leds {
++      act_led: act {
++              label = "led0";
++              linux,default-trigger = "default-on";
++              default-state = "on";
++              gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
++      };
++
++      pwr_led: pwr {
++              label = "led1";
++              linux,default-trigger = "default-on";
++              gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
++      };
++};
++
++&pwm1 {
++      status = "disabled";
++};
++
++&audio {
++      pinctrl-names = "default";
++      pinctrl-0 = <&audio_pins>;
++      brcm,disable-headphones = <1>;
++};
++
++&vc4 {
++      status = "disabled";
++};
++
++&pixelvalve0 {
++      status = "disabled";
++};
++
++&pixelvalve1 {
++      status = "disabled";
++};
++
++&pixelvalve2 {
++      status = "disabled";
++};
++
++&pixelvalve3 {
++      status = "disabled";
++};
++
++&pixelvalve4 {
++      status = "disabled";
++};
++
++&hdmi0 {
++      status = "disabled";
++};
++
++&ddc0 {
++      status = "disabled";
++};
++
++&hdmi1 {
++      status = "disabled";
++};
++
++&ddc1 {
++      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";
++
++              pwr_led_gpio = <&pwr_led>,"gpios:4";
++              pwr_led_activelow = <&pwr_led>,"gpios:8";
++              pwr_led_trigger = <&pwr_led>,"linux,default-trigger";
++
++              eth_led0 = <&phy1>,"led-modes:0";
++              eth_led1 = <&phy1>,"led-modes:4";
++
++              sd_poll_once = <&emmc2>, "non-removable?";
++              spi_dma4 = <&spi0>, "dmas:0=", <&dma40>,
++                         <&spi0>, "dmas:8=", <&dma40>;
++      };
++};
+--- a/arch/arm64/boot/dts/broadcom/Makefile
++++ b/arch/arm64/boot/dts/broadcom/Makefile
+@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb
++dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb
+ dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4.dtb
+--- /dev/null
++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-400.dts
+@@ -0,0 +1 @@
++#include "../../../../arm/boot/dts/bcm2711-rpi-400.dts"
diff --git a/target/linux/bcm27xx/patches-5.4/950-1016-overlays-Deprecate-and-delete-the-sdtweak-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-1016-overlays-Deprecate-and-delete-the-sdtweak-overlay.patch
new file mode 100644 (file)
index 0000000..fb0107c
--- /dev/null
@@ -0,0 +1,64 @@
+From 88358069ed07f16a0aab0764ed1337e540006e29 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 4 Nov 2020 11:25:02 +0000
+Subject: [PATCH] overlays: Deprecate and delete the sdtweak overlay
+
+The sdtweak overlay has been superseded by the board-specific
+sd_* parameters such as sd_poll_once, sd_overclock etc.
+
+For example, replace:
+
+    dtoverlay=sdtweak,poll_once
+
+with:
+
+    dtparam=sd_poll_once
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/overlay_map.dts    |  4 +++
+ .../arm/boot/dts/overlays/sdtweak-overlay.dts | 25 -------------------
+ 2 files changed, 4 insertions(+), 25 deletions(-)
+ delete mode 100644 arch/arm/boot/dts/overlays/sdtweak-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/overlay_map.dts
++++ b/arch/arm/boot/dts/overlays/overlay_map.dts
+@@ -61,6 +61,10 @@
+               deprecated = "use sdio,bus_width=1,gpios_22_25";
+       };
++      sdtweak {
++              deprecated = "use 'dtparam=sd_poll_once' etc.";
++      };
++
+       spi0-cs {
+               renamed = "spi0-2cs";
+       };
+--- a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/dts-v1/;
+-/plugin/;
+-
+-/* Provide backwards compatible aliases for the old sdhost dtparams. */
+-
+-/{
+-      compatible = "brcm,bcm2835";
+-
+-      fragment@0 {
+-              target = <&sdhost>;
+-              frag0: __overlay__ {
+-                      brcm,overclock-50 = <0>;
+-                      brcm,pio-limit = <1>;
+-              };
+-      };
+-
+-      __overrides__ {
+-              overclock_50     = <&frag0>,"brcm,overclock-50:0";
+-              force_pio        = <&frag0>,"brcm,force-pio?";
+-              pio_limit        = <&frag0>,"brcm,pio-limit:0";
+-              debug            = <&frag0>,"brcm,debug?";
+-              enable           = <&frag0>,"status";
+-              poll_once        = <&frag0>,"non-removable?";
+-      };
+-};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1017-overlays-Complete-the-sdtweak-excision.patch b/target/linux/bcm27xx/patches-5.4/950-1017-overlays-Complete-the-sdtweak-excision.patch
new file mode 100644 (file)
index 0000000..dc63f39
--- /dev/null
@@ -0,0 +1,57 @@
+From 572fe7f4e008792e3f14822d5ddddb37c86329fe Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 5 Nov 2020 09:54:33 +0000
+Subject: [PATCH] overlays: Complete the sdtweak excision
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/Makefile |  1 -
+ arch/arm/boot/dts/overlays/README   | 27 ++++-----------------------
+ 2 files changed, 4 insertions(+), 24 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -159,7 +159,6 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       sc16is752-spi1.dtbo \
+       sdhost.dtbo \
+       sdio.dtbo \
+-      sdtweak.dtbo \
+       sh1106-spi.dtbo \
+       smi.dtbo \
+       smi-dev.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2407,29 +2407,10 @@ Load:   <Deprecated>
+ Name:   sdtweak
+-Info:   Tunes the bcm2835-sdhost SD/MMC driver
+-        N.B. This functionality is now available via the sd_* dtparams in the
+-        base DTB.
+-Load:   dtoverlay=sdtweak,<param>=<val>
+-Params: overclock_50            Clock (in MHz) to use when the MMC framework
+-                                requests 50MHz
+-
+-        force_pio               Disable DMA support (default off)
+-
+-        pio_limit               Number of blocks above which to use DMA
+-                                (default 1)
+-
+-        debug                   Enable debug output (default off)
+-
+-        poll_once               Looks for a card once after booting. Useful
+-                                for network booting scenarios to avoid the
+-                                overhead of continuous polling. N.B. Using
+-                                this option restricts the system to using a
+-                                single card per boot (or none at all).
+-                                (default off)
+-
+-        enable                  Set to off to completely disable the interface
+-                                (default on)
++Info:   This overlay is now deprecated. Use the sd_* dtparams in the
++        base DTB, e.g. "dtoverlay=sdtweak,poll_once" becomes
++        "dtparam=sd_poll_once".
++Load:   <Deprecated>
+ Name:   sh1106-spi
diff --git a/target/linux/bcm27xx/patches-5.4/950-1018-ARM-dts-bcm27xx-Remove-enable_headphones-setting.patch b/target/linux/bcm27xx/patches-5.4/950-1018-ARM-dts-bcm27xx-Remove-enable_headphones-setting.patch
new file mode 100644 (file)
index 0000000..f3db190
--- /dev/null
@@ -0,0 +1,110 @@
+From f1d85a62da9a69fba1438e64b4fcc785abb6c957 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 5 Nov 2020 11:39:35 +0000
+Subject: [PATCH] ARM: dts: bcm27xx: Remove enable_headphones setting
+
+The enable_headphones parameter of the snd_bcm2835 module is forced
+to 1 if enable_compat_alsa is 0, so setting them both on the kernel
+command line is pointless (and, in the case of Pi 400 and Pi Zeroes,
+confusing).
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2708-rpi-zero-w.dts   | 2 +-
+ arch/arm/boot/dts/bcm2708-rpi-zero.dts     | 2 +-
+ arch/arm/boot/dts/bcm270x.dtsi             | 2 +-
+ arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 2 +-
+ arch/arm/boot/dts/bcm2710-rpi-3-b.dts      | 2 +-
+ arch/arm/boot/dts/bcm2711-rpi-4-b.dts      | 2 +-
+ arch/arm/boot/dts/bcm2711-rpi-400.dts      | 2 +-
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts      | 2 +-
+ 8 files changed, 8 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts
+@@ -11,7 +11,7 @@
+       model = "Raspberry Pi Zero W";
+       chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts
++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts
+@@ -10,7 +10,7 @@
+       model = "Raspberry Pi Zero";
+       chosen {
+-              bootargs = "coherent_pool=1M snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+ };
+--- a/arch/arm/boot/dts/bcm270x.dtsi
++++ b/arch/arm/boot/dts/bcm270x.dtsi
+@@ -3,7 +3,7 @@
+ / {
+       chosen {
+-              bootargs = "coherent_pool=1M snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+               /delete-property/ stdout-path;
+       };
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts
+@@ -12,7 +12,7 @@
+       model = "Raspberry Pi 3 Model B+";
+       chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
+@@ -12,7 +12,7 @@
+       model = "Raspberry Pi 3 Model B";
+       chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+@@ -234,7 +234,7 @@
+ / {
+       chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2711-rpi-400.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-400.dts
+@@ -234,7 +234,7 @@
+ / {
+       chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+       aliases {
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -174,7 +174,7 @@
+ / {
+       chosen {
+-              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1";
++              bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+       };
+       aliases {
diff --git a/target/linux/bcm27xx/patches-5.4/950-1019-staging-vcsm-cma-Fix-memory-leak-from-not-detaching-.patch b/target/linux/bcm27xx/patches-5.4/950-1019-staging-vcsm-cma-Fix-memory-leak-from-not-detaching-.patch
new file mode 100644 (file)
index 0000000..992adc6
--- /dev/null
@@ -0,0 +1,77 @@
+From 6ff310748f67d98d1c2c8ea75decd9dee13aa50c Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Wed, 4 Nov 2020 18:54:20 +0000
+Subject: [PATCH] staging: vcsm-cma: Fix memory leak from not
+ detaching dmabuf
+
+When importing there was a missing call to detach the buffer,
+so each import leaked the sg table entry.
+
+Actually the release process for both locally allocated and
+imported buffers is identical, so fix them to both use the same
+function.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c   | 22 ++-----------------
+ 1 file changed, 2 insertions(+), 20 deletions(-)
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -237,6 +237,7 @@ static void vc_sm_add_resource(struct vc
+ /*
+  * Cleans up imported dmabuf.
++ * Should be called with mutex held.
+  */
+ static void vc_sm_clean_up_dmabuf(struct vc_sm_buffer *buffer)
+ {
+@@ -244,7 +245,6 @@ static void vc_sm_clean_up_dmabuf(struct
+               return;
+       /* Handle cleaning up imported dmabufs */
+-      mutex_lock(&buffer->lock);
+       if (buffer->import.sgt) {
+               dma_buf_unmap_attachment(buffer->import.attach,
+                                        buffer->import.sgt,
+@@ -255,7 +255,6 @@ static void vc_sm_clean_up_dmabuf(struct
+               dma_buf_detach(buffer->dma_buf, buffer->import.attach);
+               buffer->import.attach = NULL;
+       }
+-      mutex_unlock(&buffer->lock);
+ }
+ /*
+@@ -687,23 +686,6 @@ int vc_sm_import_dmabuf_mmap(struct dma_
+ }
+ static
+-void vc_sm_import_dma_buf_release(struct dma_buf *dmabuf)
+-{
+-      struct vc_sm_buffer *buf = dmabuf->priv;
+-
+-      pr_debug("%s: Relasing dma_buf %p\n", __func__, dmabuf);
+-      mutex_lock(&buf->lock);
+-      if (!buf->imported)
+-              return;
+-
+-      buf->in_use = 0;
+-
+-      vc_sm_vpu_free(buf);
+-
+-      vc_sm_release_resource(buf);
+-}
+-
+-static
+ void *vc_sm_import_dma_buf_kmap(struct dma_buf *dmabuf,
+                               unsigned long offset)
+ {
+@@ -753,7 +735,7 @@ static const struct dma_buf_ops dma_buf_
+       .map_dma_buf = vc_sm_import_map_dma_buf,
+       .unmap_dma_buf = vc_sm_import_unmap_dma_buf,
+       .mmap = vc_sm_import_dmabuf_mmap,
+-      .release = vc_sm_import_dma_buf_release,
++      .release = vc_sm_dma_buf_release,
+       .attach = vc_sm_import_dma_buf_attach,
+       .detach = vc_sm_import_dma_buf_detatch,
+       .begin_cpu_access = vc_sm_import_dma_buf_begin_cpu_access,
diff --git a/target/linux/bcm27xx/patches-5.4/950-1020-Update-Allo-Piano-Dac-Driver-for-5.4.y-kernels.patch b/target/linux/bcm27xx/patches-5.4/950-1020-Update-Allo-Piano-Dac-Driver-for-5.4.y-kernels.patch
new file mode 100644 (file)
index 0000000..00d319e
--- /dev/null
@@ -0,0 +1,246 @@
+From 7f7ea09cdfa44c447c31db4884c1bb958d27f10a Mon Sep 17 00:00:00 2001
+From: paul-1 <6473457+paul-1@users.noreply.github.com>
+Date: Wed, 4 Nov 2020 19:11:37 -0500
+Subject: [PATCH] Update Allo Piano Dac Driver for 5.4.y kernels
+
+Add unique names to the individual dac coded drivers
+Remove some of the codec controls that are not used.
+
+Signed-off-by: Paul Hermann <paul@picoreplayer.org>
+---
+ sound/soc/bcm/allo-piano-dac-plus.c | 129 +++++++++++++++++++++-------
+ 1 file changed, 97 insertions(+), 32 deletions(-)
+
+--- a/sound/soc/bcm/allo-piano-dac-plus.c
++++ b/sound/soc/bcm/allo-piano-dac-plus.c
+@@ -2,7 +2,8 @@
+  * ALSA ASoC Machine Driver for Allo Piano DAC Plus Subwoofer
+  *
+  * Author:    Baswaraj K <jaikumar@cem-solutions.net>
+- *            Copyright 2016
++ *            Copyright 2020
++ *            based on code by David Knell <david.knell@gmail.com)
+  *            based on code by Daniel Matuschek <info@crazy-audio.com>
+  *            based on code by Florian Meier <florian.meier@koalo.de>
+  *
+@@ -276,8 +277,15 @@ static int snd_allo_piano_dual_mode_put(
+                               PCM512x_DIGITAL_VOLUME_2, 0xff);
+               list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
+-                      if (!strncmp(kctl->id.name, "Digital Playback Volume",
+-                                      sizeof(kctl->id.name))) {
++                      if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
++                              sizeof(kctl->id.name))) {
++                              mc = (struct soc_mixer_control *)
++                                      kctl->private_value;
++                              mc->rreg = mc->reg;
++                              break;
++                      }
++                      if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
++                              sizeof(kctl->id.name))) {
+                               mc = (struct soc_mixer_control *)
+                                       kctl->private_value;
+                               mc->rreg = mc->reg;
+@@ -291,13 +299,20 @@ static int snd_allo_piano_dual_mode_put(
+                                               PCM512x_DIGITAL_VOLUME_3, &right_val);
+               list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
+-                      if (!strncmp(kctl->id.name, "Digital Playback Volume",
+-                                      sizeof(kctl->id.name))) {
++                      if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
++                              sizeof(kctl->id.name))) {
+                               mc = (struct soc_mixer_control *)
+                                       kctl->private_value;
+                               mc->rreg = PCM512x_DIGITAL_VOLUME_3;
+                               break;
+                       }
++                      if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
++                              sizeof(kctl->id.name))) {
++                              mc = (struct soc_mixer_control *)
++                                      kctl->private_value;
++                              mc->rreg = PCM512x_DIGITAL_VOLUME_2;
++                              break;
++                      }
+               }
+               snd_soc_component_write(rtd->codec_dais[0]->component,
+@@ -344,13 +359,20 @@ static int snd_allo_piano_mode_put(struc
+                                               PCM512x_DIGITAL_VOLUME_2, &right_val);
+               list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
+-                      if (!strncmp(kctl->id.name, "Digital Playback Volume",
+-                                      sizeof(kctl->id.name))) {
++                      if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
++                              sizeof(kctl->id.name))) {
+                               mc = (struct soc_mixer_control *)
+                                       kctl->private_value;
+                               mc->rreg = PCM512x_DIGITAL_VOLUME_3;
+                               break;
+                       }
++                      if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
++                              sizeof(kctl->id.name))) {
++                              mc = (struct soc_mixer_control *)
++                                      kctl->private_value;
++                              mc->rreg = PCM512x_DIGITAL_VOLUME_2;
++                              break;
++                      }
+               }
+               snd_soc_component_write(rtd->codec_dais[0]->component,
+                               PCM512x_DIGITAL_VOLUME_3, left_val);
+@@ -434,12 +456,6 @@ static int pcm512x_set_reg_sub(struct sn
+       int ret = 0;
+       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+-      if (glb_ptr->dual_mode != 1) {
+-              ret = snd_soc_component_write(rtd->codec_dais[1]->component,
+-                              PCM512x_DIGITAL_VOLUME_2, (~left_val));
+-              if (ret < 0)
+-                      return ret;
+-      }
+       if (digital_gain_0db_limit) {
+               ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume",
+@@ -449,6 +465,13 @@ static int pcm512x_set_reg_sub(struct sn
+                               ret);
+       }
++      if (glb_ptr->dual_mode != 1) {
++              ret = snd_soc_component_write(rtd->codec_dais[1]->component,
++                              PCM512x_DIGITAL_VOLUME_2, (~left_val));
++              if (ret < 0)
++                      return ret;
++      }
++
+       ret = snd_soc_component_write(rtd->codec_dais[1]->component,
+                       PCM512x_DIGITAL_VOLUME_3, (~right_val));
+       if (ret < 0)
+@@ -674,7 +697,7 @@ static const struct snd_kcontrol_new all
+       SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
+                       PCM512x_DIGITAL_VOLUME_2,
+-                      PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
++                      PCM512x_DIGITAL_VOLUME_3, 0, 207, 1,
+                       pcm512x_get_reg_sub,
+                       pcm512x_set_reg_sub,
+                       digital_tlv_sub),
+@@ -688,7 +711,7 @@ static const struct snd_kcontrol_new all
+       SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
+                       PCM512x_DIGITAL_VOLUME_2,
+-                      PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
++                      PCM512x_DIGITAL_VOLUME_3, 0, 207, 1,
+                       pcm512x_get_reg_master,
+                       pcm512x_set_reg_master,
+                       digital_tlv_master),
+@@ -701,10 +724,28 @@ static const struct snd_kcontrol_new all
+                       pcm512x_set_reg_master_switch),
+ };
++static const char * const codec_ctl_pfx[] = { "Main", "Sub" };
++static const char * const codec_ctl_name[] = {
++      "Digital Playback Volume",
++      "Digital Playback Switch",
++      "Auto Mute Mono Switch",
++      "Auto Mute Switch",
++      "Auto Mute Time Left",
++      "Auto Mute Time Right",
++      "Clock Missing Period",
++      "Max Overclock DAC",
++      "Max Overclock DSP",
++      "Max Overclock PLL",
++      "Volume Ramp Down Emergency Rate",
++      "Volume Ramp Down Emergency Step"
++};
++
+ static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
+ {
+       struct snd_soc_card *card = rtd->card;
+       struct glb_pool *glb_ptr;
++      struct snd_kcontrol *kctl;
++      int i, j;
+       glb_ptr = kzalloc(sizeof(struct glb_pool), GFP_KERNEL);
+       if (!glb_ptr)
+@@ -719,12 +760,37 @@ static int snd_allo_piano_dac_init(struc
+       if (digital_gain_0db_limit) {
+               int ret;
+-              ret = snd_soc_limit_volume(card, "Digital Playback Volume",
+-                                      207);
+-              if (ret < 0)
+-                      dev_warn(card->dev, "Failed to set volume limit: %d\n",
+-                              ret);
++              //Set volume limit on both dacs
++              for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
++                      char cname[256];
++
++                      sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[0]);
++                      ret = snd_soc_limit_volume(card, cname, 207);
++                      if (ret < 0)
++                              dev_warn(card->dev, "Failed to set volume limit: %d\n",
++                                      ret);
++              }
++      }
++
++      // Remove codec controls
++      for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
++              // Start at 1, leave the Digital Volume control.
++              for (j = 1; j < ARRAY_SIZE(codec_ctl_name); j++) {
++                      char cname[256];
++
++                      sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[j]);
++                      kctl = snd_soc_card_get_kcontrol(card, cname);
++                      if (!kctl) {
++                              dev_err(rtd->card->dev, "Control %s not found\n",
++                                     cname);
++                      } else {
++                              kctl->vd[0].access =
++                                      SNDRV_CTL_ELEM_ACCESS_READWRITE;
++                              snd_ctl_remove(card->snd_card, kctl);
++                      }
++              }
+       }
++
+       return 0;
+ }
+@@ -868,10 +934,10 @@ static struct snd_soc_dai_link_component
+ };
+ SND_SOC_DAILINK_DEFS(allo_piano_dai_plus,
+-      DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
+-      DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "pcm512x-hifi"),
+-                         COMP_CODEC(NULL, "pcm512x-hifi")),
+-      DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
++      DAILINK_COMP_ARRAY(COMP_EMPTY()),
++      DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi"),
++                         COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
++      DAILINK_COMP_ARRAY(COMP_EMPTY()));
+ static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
+       {
+@@ -964,17 +1030,16 @@ static int snd_allo_piano_dac_probe(stru
+                       snd_allo_piano_dac.set_bias_level =
+                               snd_allo_piano_set_bias_level;
+-              ret = snd_soc_register_card(&snd_allo_piano_dac);
+-              if (ret < 0) {
+-                      dev_err(&pdev->dev,
+-                              "snd_soc_register_card() failed: %d\n", ret);
+-                      return ret;
+-              }
+-
+               if ((mute_gpio[0]) && (mute_gpio[1]))
+                       snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
+-              return 0;
++              ret = devm_snd_soc_register_card(&pdev->dev, &snd_allo_piano_dac);
++
++              if (ret && ret != -EPROBE_DEFER)
++                      dev_err(&pdev->dev,
++                              "snd_soc_register_card() failed: %d\n", ret);
++              return ret;
++
+       }
+       return -EINVAL;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1021-Overlay-Update-Allo-Piano-Plus-dac-driver-for-5.4.y-.patch b/target/linux/bcm27xx/patches-5.4/950-1021-Overlay-Update-Allo-Piano-Plus-dac-driver-for-5.4.y-.patch
new file mode 100644 (file)
index 0000000..68b713d
--- /dev/null
@@ -0,0 +1,30 @@
+From 244817626f3f3f5d0e5f6e2881f7046087a225ff Mon Sep 17 00:00:00 2001
+From: paul-1 <6473457+paul-1@users.noreply.github.com>
+Date: Wed, 4 Nov 2020 19:17:48 -0500
+Subject: [PATCH] Overlay: Update Allo Piano Plus dac driver for
+ 5.4.y kernels.
+
+Create unique names for the two instances of the codec driver.
+
+Signed-off-by: Paul Hermann <paul@picoreplayer.org>
+---
+ .../dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts  | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts
++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts
+@@ -23,12 +23,14 @@
+                               #sound-dai-cells = <0>;
+                               compatible = "ti,pcm5122";
+                               reg = <0x4c>;
++                              sound-name-prefix = "Main";
+                               status = "okay";
+                       };
+                       allo_pcm5122_4d: pcm5122@4d {
+                               #sound-dai-cells = <0>;
+                               compatible = "ti,pcm5122";
+                               reg = <0x4d>;
++                              sound-name-prefix = "Sub";
+                               status = "okay";
+                       };
+               };
diff --git a/target/linux/bcm27xx/patches-5.4/950-1022-Update-volume-controls-in-Allo-Piano-Dac-Plus.patch b/target/linux/bcm27xx/patches-5.4/950-1022-Update-volume-controls-in-Allo-Piano-Dac-Plus.patch
new file mode 100644 (file)
index 0000000..ab5448a
--- /dev/null
@@ -0,0 +1,141 @@
+From cc1a511f1a582e2fbf9fa1e257f6b88cbcc2e0d9 Mon Sep 17 00:00:00 2001
+From: paul-1 <6473457+paul-1@users.noreply.github.com>
+Date: Sat, 7 Nov 2020 12:01:44 -0500
+Subject: [PATCH] Update volume controls in Allo Piano Dac Plus
+
+Put control scaling back to 255.
+Clean up what master/sub volume controls set in codec.
+Remove more unneeded mixer controls.
+
+Signed-off-by: Paul Hermann <paul@picoreplayer.org>
+---
+ sound/soc/bcm/allo-piano-dac-plus.c | 56 +++++++++++++++++------------
+ 1 file changed, 33 insertions(+), 23 deletions(-)
+
+--- a/sound/soc/bcm/allo-piano-dac-plus.c
++++ b/sound/soc/bcm/allo-piano-dac-plus.c
+@@ -420,6 +420,7 @@ static int pcm512x_get_reg_sub(struct sn
+       unsigned int right_val = 0;
+       int ret;
+       rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
++
+       ret = snd_soc_component_read(rtd->codec_dais[1]->component,
+                       PCM512x_DIGITAL_VOLUME_3, &right_val);
+       if (ret < 0)
+@@ -465,17 +466,20 @@ static int pcm512x_set_reg_sub(struct sn
+                               ret);
+       }
+-      if (glb_ptr->dual_mode != 1) {
++      // When in Dual Mono, Sub vol control should not set anything.
++      if (glb_ptr->dual_mode != 1) { //Not in Dual Mono mode
++
+               ret = snd_soc_component_write(rtd->codec_dais[1]->component,
+                               PCM512x_DIGITAL_VOLUME_2, (~left_val));
+               if (ret < 0)
+                       return ret;
+-      }
+-      ret = snd_soc_component_write(rtd->codec_dais[1]->component,
+-                      PCM512x_DIGITAL_VOLUME_3, (~right_val));
+-      if (ret < 0)
+-              return ret;
++              ret = snd_soc_component_write(rtd->codec_dais[1]->component,
++                              PCM512x_DIGITAL_VOLUME_3, (~right_val));
++              if (ret < 0)
++                      return ret;
++
++      }
+       return 1;
+ }
+@@ -540,7 +544,7 @@ static int pcm512x_get_reg_master(struct
+       if ( ret < 0)
+               return ret;
+-      if (glb_ptr->dual_mode == 1) {
++      if (glb_ptr->dual_mode == 1) {  // in Dual Mono mode
+               ret = snd_soc_component_read(rtd->codec_dais[1]->component,
+                               PCM512x_DIGITAL_VOLUME_3, &right_val);
+               if (ret < 0)
+@@ -582,8 +586,21 @@ static int pcm512x_set_reg_master(struct
+                               ret);
+       }
+-      if (glb_ptr->dual_mode != 1) {
++      if (glb_ptr->dual_mode == 1) { //in Dual Mono Mode
++
++              ret = snd_soc_component_write(rtd->codec_dais[0]->component,
++                              PCM512x_DIGITAL_VOLUME_2, (~left_val));
++              if (ret < 0)
++                      return ret;
++
+               ret = snd_soc_component_write(rtd->codec_dais[1]->component,
++                              PCM512x_DIGITAL_VOLUME_3, (~right_val));
++              if (ret < 0)
++                      return ret;
++
++      } else {
++
++              ret = snd_soc_component_write(rtd->codec_dais[0]->component,
+                               PCM512x_DIGITAL_VOLUME_2, (~left_val));
+               if (ret < 0)
+                       return ret;
+@@ -594,16 +611,6 @@ static int pcm512x_set_reg_master(struct
+                       return ret;
+       }
+-
+-      ret = snd_soc_component_write(rtd->codec_dais[1]->component,
+-                      PCM512x_DIGITAL_VOLUME_3, (~right_val));
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = snd_soc_component_write(rtd->codec_dais[0]->component,
+-                      PCM512x_DIGITAL_VOLUME_2, (~left_val));
+-      if (ret < 0)
+-              return ret;
+       return 1;
+ }
+@@ -697,7 +704,7 @@ static const struct snd_kcontrol_new all
+       SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
+                       PCM512x_DIGITAL_VOLUME_2,
+-                      PCM512x_DIGITAL_VOLUME_3, 0, 207, 1,
++                      PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
+                       pcm512x_get_reg_sub,
+                       pcm512x_set_reg_sub,
+                       digital_tlv_sub),
+@@ -711,7 +718,7 @@ static const struct snd_kcontrol_new all
+       SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
+                       PCM512x_DIGITAL_VOLUME_2,
+-                      PCM512x_DIGITAL_VOLUME_3, 0, 207, 1,
++                      PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
+                       pcm512x_get_reg_master,
+                       pcm512x_set_reg_master,
+                       digital_tlv_master),
+@@ -737,7 +744,11 @@ static const char * const codec_ctl_name
+       "Max Overclock DSP",
+       "Max Overclock PLL",
+       "Volume Ramp Down Emergency Rate",
+-      "Volume Ramp Down Emergency Step"
++      "Volume Ramp Down Emergency Step",
++      "Volume Ramp Up Rate",
++      "Volume Ramp Down Rate",
++      "Volume Ramp Up Step",
++      "Volume Ramp Down Step"
+ };
+ static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
+@@ -774,8 +785,7 @@ static int snd_allo_piano_dac_init(struc
+       // Remove codec controls
+       for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
+-              // Start at 1, leave the Digital Volume control.
+-              for (j = 1; j < ARRAY_SIZE(codec_ctl_name); j++) {
++              for (j = 0; j < ARRAY_SIZE(codec_ctl_name); j++) {
+                       char cname[256];
+                       sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[j]);
diff --git a/target/linux/bcm27xx/patches-5.4/950-1023-media-i2c-imx219-Selection-compliance-fixes.patch b/target/linux/bcm27xx/patches-5.4/950-1023-media-i2c-imx219-Selection-compliance-fixes.patch
new file mode 100644 (file)
index 0000000..600e25e
--- /dev/null
@@ -0,0 +1,80 @@
+From de47ea073936726d9a5ad843908fd3074c1fb8f0 Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hverkuil@xs4all.nl>
+Date: Wed, 5 Aug 2020 12:57:21 +0200
+Subject: [PATCH] media: i2c: imx219: Selection compliance fixes
+
+To comply with the intended usage of the V4L2 selection target when
+used to retrieve a sensor image properties, adjust the rectangles
+returned by the imx219 driver.
+
+The top/left crop coordinates of the TGT_CROP rectangle were set to
+(0, 0) instead of (8, 8) which is the offset from the larger physical
+pixel array rectangle. This was also a mismatch with the default values
+crop rectangle value, so this is corrected. Found with v4l2-compliance.
+
+While at it, add V4L2_SEL_TGT_CROP_BOUNDS support: CROP_DEFAULT and
+CROP_BOUNDS have the same size as the non-active pixels are not readable
+using the selection API. Found with v4l2-compliance.
+
+Fixes: e6d4ef7d58aa7 ("media: i2c: imx219: Implement get_selection")
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+[reword commit message, use macros for pixel offsets]
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+---
+ drivers/media/i2c/imx219.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -485,8 +485,8 @@ static const struct imx219_mode supporte
+               .width = 3280,
+               .height = 2464,
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = IMX219_PIXEL_ARRAY_LEFT,
++                      .top = IMX219_PIXEL_ARRAY_TOP,
+                       .width = 3280,
+                       .height = 2464
+               },
+@@ -501,8 +501,8 @@ static const struct imx219_mode supporte
+               .width = 1920,
+               .height = 1080,
+               .crop = {
+-                      .left = 680,
+-                      .top = 692,
++                      .left = 688,
++                      .top = 700,
+                       .width = 1920,
+                       .height = 1080
+               },
+@@ -517,8 +517,8 @@ static const struct imx219_mode supporte
+               .width = 1640,
+               .height = 1232,
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = IMX219_PIXEL_ARRAY_LEFT,
++                      .top = IMX219_PIXEL_ARRAY_TOP,
+                       .width = 3280,
+                       .height = 2464
+               },
+@@ -533,8 +533,8 @@ static const struct imx219_mode supporte
+               .width = 640,
+               .height = 480,
+               .crop = {
+-                      .left = 1000,
+-                      .top = 752,
++                      .left = 1008,
++                      .top = 760,
+                       .width = 1280,
+                       .height = 960
+               },
+@@ -1093,6 +1093,7 @@ static int imx219_get_selection(struct v
+               return 0;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.top = IMX219_PIXEL_ARRAY_TOP;
+               sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
+               sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1024-media-bcm2835-unicam-Correctly-handle-error-propagat.patch b/target/linux/bcm27xx/patches-5.4/950-1024-media-bcm2835-unicam-Correctly-handle-error-propagat.patch
new file mode 100644 (file)
index 0000000..906e45b
--- /dev/null
@@ -0,0 +1,27 @@
+From 85dae0158c3ba741e2cb815879b4d5d55b3254d7 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Wed, 2 Dec 2020 15:22:23 +0000
+Subject: [PATCH] media: bcm2835-unicam: Correctly handle error
+ propagation for stream on
+
+On a failure in start_streaming(), the error code would not propagate to
+the calling function on all conditions. This would cause the userland
+caller to not know of the failure.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1730,8 +1730,7 @@ err_disable_unicam:
+       unicam_disable(dev);
+       clk_disable_unprepare(dev->clock);
+ err_vpu_clock:
+-      ret = clk_set_min_rate(dev->vpu_clock, 0);
+-      if (ret)
++      if (clk_set_min_rate(dev->vpu_clock, 0))
+               unicam_err(dev, "failed to reset the VPU clock\n");
+       clk_disable_unprepare(dev->vpu_clock);
+ err_pm_put:
diff --git a/target/linux/bcm27xx/patches-5.4/950-1025-media-bcm2835-unicam-Return-early-from-stop_streamin.patch b/target/linux/bcm27xx/patches-5.4/950-1025-media-bcm2835-unicam-Return-early-from-stop_streamin.patch
new file mode 100644 (file)
index 0000000..92c699a
--- /dev/null
@@ -0,0 +1,64 @@
+From 1e888ff376c880b2803aecea3f69d28dc2ae4349 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Wed, 2 Dec 2020 15:26:09 +0000
+Subject: [PATCH] media: bcm2835-unicam: Return early from
+ stop_streaming() if stopped
+
+clk_disable_unprepare() is called unconditionally in stop_streaming().
+This is incorrect in the cases where start_streaming() fails, and
+unprepares all clocks as part of the failure cleanup. To avoid this,
+ensure that clk_disable_unprepare() is only called in stop_streaming()
+if the clocks are in a prepared state.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -426,6 +426,8 @@ struct unicam_device {
+       struct clk *clock;
+       /* vpu clock handle */
+       struct clk *vpu_clock;
++      /* clock status for error handling */
++      bool clocks_enabled;
+       /* V4l2 device */
+       struct v4l2_device v4l2_dev;
+       struct media_device mdev;
+@@ -1724,6 +1726,7 @@ static int unicam_start_streaming(struct
+               goto err_disable_unicam;
+       }
++      dev->clocks_enabled = true;
+       return 0;
+ err_disable_unicam:
+@@ -1750,8 +1753,6 @@ static void unicam_stop_streaming(struct
+       node->streaming = false;
+       if (node->pad_id == IMAGE_PAD) {
+-              int ret;
+-
+               /*
+                * Stop streaming the sensor and disable the peripheral.
+                * We cannot continue streaming embedded data with the
+@@ -1762,12 +1763,13 @@ static void unicam_stop_streaming(struct
+               unicam_disable(dev);
+-              ret = clk_set_min_rate(dev->vpu_clock, 0);
+-              if (ret)
+-                      unicam_err(dev, "failed to reset the min VPU clock\n");
++              if (dev->clocks_enabled) {
++                      if (clk_set_min_rate(dev->vpu_clock, 0))
++                              unicam_err(dev, "failed to reset the min VPU clock\n");
+-              clk_disable_unprepare(dev->vpu_clock);
+-              clk_disable_unprepare(dev->clock);
++                      clk_disable_unprepare(dev->vpu_clock);
++                      clk_disable_unprepare(dev->clock);
++              }
+               unicam_runtime_put(dev);
+       } else if (node->pad_id == METADATA_PAD) {
diff --git a/target/linux/bcm27xx/patches-5.4/950-1026-media-bcm2835-unicam-Clear-clock-state-when-stopping.patch b/target/linux/bcm27xx/patches-5.4/950-1026-media-bcm2835-unicam-Clear-clock-state-when-stopping.patch
new file mode 100644 (file)
index 0000000..3163107
--- /dev/null
@@ -0,0 +1,25 @@
+From 210f956f55dcc457386d8a4c9b4b5803c671d28a Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Wed, 2 Dec 2020 16:48:41 +0000
+Subject: [PATCH] media: bcm2835-unicam: Clear clock state when
+ stopping streaming
+
+Commit 65e08c465020d4c5b51afb452efc2246d80fd66f failed to clear the
+clock state when the device stopped streaming. Fix this, as it might
+again cause the same problems when doing an unprepare.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-unicam.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
++++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
+@@ -1769,6 +1769,7 @@ static void unicam_stop_streaming(struct
+                       clk_disable_unprepare(dev->vpu_clock);
+                       clk_disable_unprepare(dev->clock);
++                      dev->clocks_enabled = false;
+               }
+               unicam_runtime_put(dev);
diff --git a/target/linux/bcm27xx/patches-5.4/950-1027-ARM-dts-CM4-audio-pins-are-not-connected.patch b/target/linux/bcm27xx/patches-5.4/950-1027-ARM-dts-CM4-audio-pins-are-not-connected.patch
new file mode 100644 (file)
index 0000000..8ac8243
--- /dev/null
@@ -0,0 +1,21 @@
+From a679b9471f0ed1496b7d853becf38001282a738f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 7 Dec 2020 09:35:57 +0000
+Subject: [PATCH] ARM: dts: CM4 audio pins are not connected
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -434,8 +434,6 @@
+ &gpio {
+       audio_pins: audio_pins {
+-              brcm,pins = <40 41>;
+-              brcm,function = <4>;
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-1028-overlays-Add-PCF85063-and-PCF85063A-to-i2c-rtc.patch b/target/linux/bcm27xx/patches-5.4/950-1028-overlays-Add-PCF85063-and-PCF85063A-to-i2c-rtc.patch
new file mode 100644 (file)
index 0000000..f55f9f6
--- /dev/null
@@ -0,0 +1,339 @@
+From ecfd415e5ae3fc05bf0c2b16a80f1d3e00447896 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 7 Dec 2020 08:49:53 +0000
+Subject: [PATCH] overlays: Add PCF85063 and PCF85063A to i2c-rtc
+
+Add support for the PCF85063 and PCF85063A RTC devices to the
+i2c-rtc overlay.
+
+Also enable the device to be used on i2c0 (i2c_vc) on GPIOs 0&1 (use
+parameter "i2c0") and GPIOs 44 & 45 (use parameter "i2c_csi_dsi").
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README             |  8 ++
+ .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 98 ++++++++++---------
+ 2 files changed, 61 insertions(+), 45 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1243,6 +1243,10 @@ Params: abx80x                  Select o
+         pcf2129                 Select the PCF2129 device
++        pcf85063                Select the PCF85363 device
++
++        pcf85063a               Select the PCF85363A device
++
+         pcf8523                 Select the PCF8523 device
+         pcf85363                Select the PCF85363 device
+@@ -1255,6 +1259,10 @@ Params: abx80x                  Select o
+         sd3078                  Select the ZXW Shenzhen whwave SD3078 device
++        i2c0                    Choose the I2C0 bus on GPIOs 0&1
++
++        i2c_csi_dsi             Choose the I2C0 bus on GPIOs 44&45
++
+         addr                    Sets the address for the RTC. Note that the
+                                 device must be configured to use the specified
+                                 address.
+--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts
+@@ -6,235 +6,238 @@
+       compatible = "brcm,bcm2835";
+       fragment@0 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       abx80x: abx80x@69 {
+                               compatible = "abracon,abx80x";
+                               reg = <0x69>;
+                               abracon,tc-diode = "standard";
+                               abracon,tc-resistor = <0>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@1 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       ds1307: ds1307@68 {
+                               compatible = "dallas,ds1307";
+                               reg = <0x68>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@2 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       ds1339: ds1339@68 {
+                               compatible = "dallas,ds1339";
+                               trickle-resistor-ohms = <0>;
+                               reg = <0x68>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@3 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       ds3231: ds3231@68 {
+                               compatible = "maxim,ds3231";
+                               reg = <0x68>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@4 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       mcp7940x: mcp7940x@6f {
+                               compatible = "microchip,mcp7940x";
+                               reg = <0x6f>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@5 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       mcp7941x: mcp7941x@6f {
+                               compatible = "microchip,mcp7941x";
+                               reg = <0x6f>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@6 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       pcf2127@51 {
+                               compatible = "nxp,pcf2127";
+                               reg = <0x51>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@7 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       pcf8523: pcf8523@68 {
+                               compatible = "nxp,pcf8523";
+                               reg = <0x68>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@8 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       pcf8563: pcf8563@51 {
+                               compatible = "nxp,pcf8563";
+                               reg = <0x51>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@9 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       m41t62: m41t62@68 {
+                               compatible = "st,m41t62";
+                               reg = <0x68>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@10 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       rv3028: rv3028@52 {
+                               compatible = "microcrystal,rv3028";
+                               reg = <0x52>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@11 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       pcf2129@51 {
+                               compatible = "nxp,pcf2129";
+                               reg = <0x51>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@12 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+              __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       pcf85363@51 {
+                               compatible = "nxp,pcf85363";
+                               reg = <0x51>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@13 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       rv1805: rv1805@69 {
+                               compatible = "microcrystal,rv1805";
+                               reg = <0x69>;
+                               abracon,tc-diode = "standard";
+                               abracon,tc-resistor = <0>;
+-                              status = "okay";
+                       };
+               };
+       };
+       fragment@14 {
+-              target = <&i2c_arm>;
++              target = <&i2cbus>;
+               __dormant__ {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+-                      status = "okay";
+                       sd3078: sd3078@32 {
+                               compatible = "whwave,sd3078";
+                               reg = <0x32>;
+-                              status = "okay";
+                       };
+               };
+       };
++      fragment@15 {
++              target = <&i2cbus>;
++             __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pcf85063@51 {
++                              compatible = "nxp,pcf85063";
++                              reg = <0x51>;
++                      };
++              };
++      };
++
++      fragment@16 {
++              target = <&i2cbus>;
++             __dormant__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      pcf85063a@51 {
++                              compatible = "nxp,pcf85063a";
++                              reg = <0x51>;
++                      };
++              };
++      };
++
++      frag100: fragment@100 {
++              target = <&i2c_arm>;
++              i2cbus: __overlay__ {
++                      status = "okay";
++              };
++      };
++
+       __overrides__ {
+               abx80x = <0>,"+0";
+               ds1307 = <0>,"+1";
+@@ -251,6 +254,11 @@
+               pcf85363 = <0>,"+12";
+               rv1805 = <0>,"+13";
+               sd3078 = <0>,"+14";
++              pcf85063 = <0>,"+15";
++              pcf85063a = <0>,"+16";
++
++              i2c0 = <&frag100>, "target:0=",<&i2c0>;
++              i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>;
+               addr = <&abx80x>, "reg:0",
+                      <&ds1307>, "reg:0",
diff --git a/target/linux/bcm27xx/patches-5.4/950-1029-overlays-Fix-cut-and-paste-error-in-README.patch b/target/linux/bcm27xx/patches-5.4/950-1029-overlays-Fix-cut-and-paste-error-in-README.patch
new file mode 100644 (file)
index 0000000..4741dae
--- /dev/null
@@ -0,0 +1,24 @@
+From 27f9953df117db0f38c5e597290435ecd6f3ed10 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Mon, 7 Dec 2020 17:18:39 +0000
+Subject: [PATCH] overlays: Fix cut-and-paste error in README
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1243,9 +1243,9 @@ Params: abx80x                  Select o
+         pcf2129                 Select the PCF2129 device
+-        pcf85063                Select the PCF85363 device
++        pcf85063                Select the PCF85063 device
+-        pcf85063a               Select the PCF85363A device
++        pcf85063a               Select the PCF85063A device
+         pcf8523                 Select the PCF8523 device
diff --git a/target/linux/bcm27xx/patches-5.4/950-1030-media-i2c-imx477-Selection-compliance-fixes.patch b/target/linux/bcm27xx/patches-5.4/950-1030-media-i2c-imx477-Selection-compliance-fixes.patch
new file mode 100644 (file)
index 0000000..e2ed71b
--- /dev/null
@@ -0,0 +1,80 @@
+From cf3885ed8bb4194c5653a9a933b4ea669cdb51c2 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Wed, 9 Dec 2020 11:30:12 +0000
+Subject: [PATCH] media: i2c: imx477: Selection compliance fixes
+
+To comply with the intended usage of the V4L2 selection target when
+used to retrieve a sensor image properties, adjust the rectangles
+returned by the imx477 driver.
+
+The top/left crop coordinates of the TGT_CROP rectangle were set to
+(0, 0) instead of (8, 16) which is the offset from the larger physical
+pixel array rectangle. This was also a mismatch with the default values
+crop rectangle value, so this is corrected. Found with v4l2-compliance.
+
+While at it, add V4L2_SEL_TGT_CROP_BOUNDS support: CROP_DEFAULT and
+CROP_BOUNDS have the same size as the non-active pixels are not readable
+using the selection API. Found with v4l2-compliance.
+
+This commit mirrors 543790f777ba1b3264c168c653db6d415e7c983f done for
+the imx219 sensor.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ drivers/media/i2c/imx477.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/media/i2c/imx477.c
++++ b/drivers/media/i2c/imx477.c
+@@ -900,8 +900,8 @@ static const struct imx477_mode supporte
+               .height = 3040,
+               .line_length_pix = 0x5dc0,
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = IMX477_PIXEL_ARRAY_LEFT,
++                      .top = IMX477_PIXEL_ARRAY_TOP,
+                       .width = 4056,
+                       .height = 3040,
+               },
+@@ -924,8 +924,8 @@ static const struct imx477_mode supporte
+               .height = 1520,
+               .line_length_pix = 0x31c4,
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = IMX477_PIXEL_ARRAY_LEFT,
++                      .top = IMX477_PIXEL_ARRAY_TOP,
+                       .width = 4056,
+                       .height = 3040,
+               },
+@@ -948,8 +948,8 @@ static const struct imx477_mode supporte
+               .height = 1080,
+               .line_length_pix = 0x31c4,
+               .crop = {
+-                      .left = 0,
+-                      .top = 440,
++                      .left = IMX477_PIXEL_ARRAY_LEFT,
++                      .top = IMX477_PIXEL_ARRAY_TOP + 440,
+                       .width = 4056,
+                       .height = 2600,
+               },
+@@ -983,8 +983,8 @@ static const struct imx477_mode supporte
+                        * rectangle once the driver is expanded to represent
+                        * its processing blocks with multiple subdevs.
+                        */
+-                      .left = 4,
+-                      .top = 0,
++                      .left = IMX477_PIXEL_ARRAY_LEFT + 4,
++                      .top = IMX477_PIXEL_ARRAY_TOP,
+                       .width = 4052,
+                       .height = 3040,
+               },
+@@ -1696,6 +1696,7 @@ static int imx477_get_selection(struct v
+               return 0;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.left = IMX477_PIXEL_ARRAY_LEFT;
+               sel->r.top = IMX477_PIXEL_ARRAY_TOP;
+               sel->r.width = IMX477_PIXEL_ARRAY_WIDTH;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch b/target/linux/bcm27xx/patches-5.4/950-1031-net-lan78xx-Ack-pending-PHY-ints-when-resetting.patch
new file mode 100644 (file)
index 0000000..2dc2a13
--- /dev/null
@@ -0,0 +1,32 @@
+From 598d6389f41c1e01b70df7d8b1056c3839e0c1c2 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 15 Dec 2020 16:38:37 +0000
+Subject: [PATCH] net: lan78xx: Ack pending PHY ints when resetting
+
+lan78xx_link_reset explicitly clears the MAC's view of the PHY's IRQ
+status. In doing so it potentially leaves the PHY with a pending
+interrupt that will never be acknowledged, at which point no further
+interrupts will be generated.
+
+Avoid the problem by acknowledging any pending PHY interrupt after
+clearing the MAC's status bit.
+
+See: https://github.com/raspberrypi/linux/issues/2937
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ drivers/net/usb/lan78xx.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -1181,6 +1181,9 @@ static int lan78xx_link_reset(struct lan
+       if (unlikely(ret < 0))
+               return -EIO;
++      /* Acknowledge any pending PHY interrupt, lest it be the last */
++      phy_read(phydev, LAN88XX_INT_STS);
++
+       phy_read_status(phydev);
+       if (!phydev->link && dev->link_on) {
diff --git a/target/linux/bcm27xx/patches-5.4/950-1032-overlays-mpu6050-Add-addr-parameter.patch b/target/linux/bcm27xx/patches-5.4/950-1032-overlays-mpu6050-Add-addr-parameter.patch
new file mode 100644 (file)
index 0000000..543b07a
--- /dev/null
@@ -0,0 +1,36 @@
+From fcf08ed99d1421158ca913a7b6a4893c31ee1bd5 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 15 Dec 2020 17:02:17 +0000
+Subject: [PATCH] overlays: mpu6050: Add 'addr' parameter
+
+The mpu6050 starts up at address 0x68 by default, but can be set to
+0x69 if the ADO pin is pulled high. Give the overlay an addr parameter
+to allow devices at the alternate address to be used.
+
+See: https://github.com/Hexxeh/rpi-firmware/issues/252
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/README              | 1 +
+ arch/arm/boot/dts/overlays/mpu6050-overlay.dts | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1876,6 +1876,7 @@ Name:   mpu6050
+ Info:   Overlay for i2c connected mpu6050 imu
+ Load:   dtoverlay=mpu6050,<param>=<val>
+ Params: interrupt               GPIO pin for interrupt (default 4)
++        addr                    I2C address of the device (default 0x68)
+ Name:   mz61581
+--- a/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
++++ b/arch/arm/boot/dts/overlays/mpu6050-overlay.dts
+@@ -24,5 +24,6 @@
+         __overrides__ {
+                 interrupt = <&mpu6050>,"interrupts:0";
++                addr = <&mpu6050>,"reg:0";
+         };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-1033-overlays-Add-missing-addresses-to-ads1015-ads1115.patch b/target/linux/bcm27xx/patches-5.4/950-1033-overlays-Add-missing-addresses-to-ads1015-ads1115.patch
new file mode 100644 (file)
index 0000000..6db63af
--- /dev/null
@@ -0,0 +1,41 @@
+From 0a8f3e6fcdbad71c0c7e993f27117f3873438e5d Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 16 Dec 2020 09:28:17 +0000
+Subject: [PATCH] overlays: Add missing addresses to ads1015/ads1115
+
+The overlays for the ads1015 and ads1115 I2C ADCs omitted the addresses
+in the main device node names. As well as breaking the conventions for
+I2C devices, this prevents the firmware from renaming them when the
+"reg" property is modified, which in turn stops the overlays from being
+instantiated multiple times.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=294465
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/overlays/ads1015-overlay.dts | 2 +-
+ arch/arm/boot/dts/overlays/ads1115-overlay.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/ads1015-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts
+@@ -13,7 +13,7 @@
+             #address-cells = <1>;
+             #size-cells = <0>;
+             status = "okay";
+-            ads1015: ads1015 {
++            ads1015: ads1015@48 {
+                 compatible = "ti,ads1015";
+                 status = "okay";
+                 #address-cells = <1>;
+--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts
++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts
+@@ -15,7 +15,7 @@
+                       #size-cells = <0>;
+                       status = "okay";
+-                      ads1115: ads1115 {
++                      ads1115: ads1115@48 {
+                               compatible = "ti,ads1115";
+                               status = "okay";
+                               #address-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1034-media-i2c-ov5647-Selection-compliance-fixes.patch b/target/linux/bcm27xx/patches-5.4/950-1034-media-i2c-ov5647-Selection-compliance-fixes.patch
new file mode 100644 (file)
index 0000000..58ba7e1
--- /dev/null
@@ -0,0 +1,88 @@
+From f05add64bf89b04310bc78606a5c70c0e97cb8b8 Mon Sep 17 00:00:00 2001
+From: Paul Elder <paul.elder@ideasonboard.com>
+Date: Tue, 22 Dec 2020 14:27:46 +0900
+Subject: [PATCH] media: i2c: ov5647: Selection compliance fixes
+
+To comply with the intended usage of the V4L2 selection target when
+used to retrieve a sensor image properties, adjust the rectangles
+returned by the ov5647 driver.
+
+The top/left crop coordinates of the TGT_CROP rectangle were set to
+(0, 0) instead of (16, 16) which is the offset from the larger physical
+pixel array rectangle. This was also a mismatch with the default values
+crop rectangle value, so this is corrected. Found with v4l2-compliance.
+
+While at it, add V4L2_SEL_TGT_CROP_BOUNDS support: CROP_DEFAULT and
+CROP_BOUNDS have the same size as the non-active pixels are not readable
+using the selection API. Found with v4l2-compliance.
+
+Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
+---
+ drivers/media/i2c/ov5647.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/drivers/media/i2c/ov5647.c
++++ b/drivers/media/i2c/ov5647.c
+@@ -606,8 +606,8 @@ static struct ov5647_mode supported_mode
+                       .height = 480
+               },
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = OV5647_PIXEL_ARRAY_LEFT,
++                      .top = OV5647_PIXEL_ARRAY_TOP,
+                       .width = 1280,
+                       .height = 960,
+               },
+@@ -632,8 +632,8 @@ static struct ov5647_mode supported_mode
+                       .height = 1944
+               },
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = OV5647_PIXEL_ARRAY_LEFT,
++                      .top = OV5647_PIXEL_ARRAY_TOP,
+                       .width = 2592,
+                       .height = 1944
+               },
+@@ -656,8 +656,8 @@ static struct ov5647_mode supported_mode
+                       .height = 1080
+               },
+               .crop = {
+-                      .left = 348,
+-                      .top = 434,
++                      .left = 364,
++                      .top = 450,
+                       .width = 1928,
+                       .height = 1080,
+               },
+@@ -679,8 +679,8 @@ static struct ov5647_mode supported_mode
+                       .height = 972
+               },
+               .crop = {
+-                      .left = 0,
+-                      .top = 0,
++                      .left = OV5647_PIXEL_ARRAY_LEFT,
++                      .top = OV5647_PIXEL_ARRAY_TOP,
+                       .width = 2592,
+                       .height = 1944,
+               },
+@@ -703,8 +703,8 @@ static struct ov5647_mode supported_mode
+                       .height = 480
+               },
+               .crop = {
+-                      .left = 16,
+-                      .top = 0,
++                      .left = OV5647_PIXEL_ARRAY_LEFT,
++                      .top = OV5647_PIXEL_ARRAY_TOP,
+                       .width = 2560,
+                       .height = 1920,
+               },
+@@ -1080,6 +1080,7 @@ static int ov5647_get_selection(struct v
+               return 0;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
++      case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.top = OV5647_PIXEL_ARRAY_TOP;
+               sel->r.left = OV5647_PIXEL_ARRAY_LEFT;
+               sel->r.width = OV5647_PIXEL_ARRAY_WIDTH;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1035-Add-overlay-for-Seeed-Studio-CAN-BUS-FD-HAT-4034.patch b/target/linux/bcm27xx/patches-5.4/950-1035-Add-overlay-for-Seeed-Studio-CAN-BUS-FD-HAT-4034.patch
new file mode 100644 (file)
index 0000000..a5bbbdd
--- /dev/null
@@ -0,0 +1,217 @@
+From 4a314a9b9d91cacbf6be9dd521cf3abd3ae8bcef Mon Sep 17 00:00:00 2001
+From: menschel <menschel.p@posteo.de>
+Date: Wed, 30 Dec 2020 21:55:34 +0100
+Subject: [PATCH] Add overlay for Seeed Studio CAN BUS FD HAT (#4034)
+
+This patch adds the overlay for the Seeed Studio CAN BUS FD HAT
+with two CAN FD Channels and an RTC.
+https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html
+
+The overlay was generated by
+ovmerge -c mcp251xfd-overlay.dts,spi0-0,interrupt=25 \
+           mcp251xfd-overlay.dts,spi0-1,interrupt=24 \
+           i2c-rtc-overlay.dts,pcf85063
+
+
+Also, add description on how to generate overlays
+
+Signed-off-by: Patrick Menschel <menschel.p@posteo.de>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |  46 +++++++
+ .../dts/overlays/seeed-can-fd-hat-overlay.dts | 117 ++++++++++++++++++
+ 3 files changed, 164 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/seeed-can-fd-hat-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -159,6 +159,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       sc16is752-spi1.dtbo \
+       sdhost.dtbo \
+       sdio.dtbo \
++      seeed-can-fd-hat.dtbo \
+       sh1106-spi.dtbo \
+       smi.dtbo \
+       smi-dev.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -81,6 +81,44 @@ Parameters usually have default values,
+ mandatory. See the list of overlays below for a description of the parameters
+ and their defaults.
++Making new Overlays based on existing Overlays
++==============================================
++
++Recent overlays have been designed in a more general way, so that they can be
++adapted to hardware by changing their parameters. When you have additional
++hardware with more than one device of a kind, you end up using the same overlay
++multiple times with other parameters, e.g.
++
++    # 2 CAN FD interfaces on spi but with different pins
++    dtoverlay=mcp251xfd,spi0-0,interrupt=25
++    dtoverlay=mcp251xfd,spi0-1,interrupt=24
++
++    # a realtime clock on i2c
++    dtoverlay=i2c-rtc,pcf85063
++
++While this approach does work, it requires knowledge about the hardware design.
++It is more feasible to simplify things for the end user by providing a single
++overlay as it is done the traditional way.
++
++A new overlay can be generated by using ovmerge utility.
++https://github.com/raspberrypi/utils/blob/master/ovmerge/ovmerge
++
++To generate an overlay for the above configuration we pass the configuration
++to ovmerge and add the -c flag.
++
++    ovmerge -c mcp251xfd-overlay.dts,spi0-0,interrupt=25 \
++               mcp251xfd-overlay.dts,spi0-1,interrupt=24 \
++               i2c-rtc-overlay.dts,pcf85063 \
++    >> merged-overlay.dts
++
++The -c option writes the command above as a comment into the overlay as
++a marker that this overlay is generated and how it was generated.
++After compiling the overlay it can be loaded in a single line.
++
++    dtoverlay=merged
++
++It does the same as the original configuration but without parameters.
++
+ The Overlay and Parameter Reference
+ ===================================
+@@ -2422,6 +2460,14 @@ Info:   This overlay is now deprecated.
+ Load:   <Deprecated>
++Name:   seeed-can-fd-hat
++Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels and an
++        RTC.
++        https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html
++Load:   dtoverlay=seeed-can-fd-hat
++Params: <None>
++
++
+ Name:   sh1106-spi
+ Info:   Overlay for SH1106 OLED via SPI using fbtft staging driver.
+ Load:   dtoverlay=sh1106-spi,<param>=<val>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/seeed-can-fd-hat-overlay.dts
+@@ -0,0 +1,117 @@
++// redo: ovmerge -c mcp251xfd-overlay.dts,spi0-0,interrupt=25 mcp251xfd-overlay.dts,spi0-1,interrupt=24 i2c-rtc-overlay.dts,pcf85063
++
++// Device tree overlay for https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html 
++
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/pinctrl/bcm2835.h>
++
++/ {
++      compatible = "brcm,bcm2835";
++      fragment@0 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++      fragment@1 {
++              target = <&gpio>;
++              __overlay__ {
++                      mcp251xfd_pins: mcp251xfd_spi0_0_pins {
++                              brcm,pins = <25>;
++                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
++                      };
++              };
++      };
++      fragment@2 {
++              target-path = "/clocks";
++              __overlay__ {
++                      clk_mcp251xfd_osc: mcp251xfd-spi0-0-osc {
++                              #clock-cells = <0>;
++                              compatible = "fixed-clock";
++                              clock-frequency = <40000000>;
++                      };
++              };
++      };
++      fragment@3 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      mcp251xfd@0 {
++                              compatible = "microchip,mcp251xfd";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&mcp251xfd_pins>;
++                              spi-max-frequency = <20000000>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
++                              clocks = <&clk_mcp251xfd_osc>;
++                      };
++              };
++      };
++      fragment@4 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++      fragment@5 {
++              target = <&gpio>;
++              __overlay__ {
++                      mcp251xfd_pins_1: mcp251xfd_spi0_1_pins {
++                              brcm,pins = <24>;
++                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
++                      };
++              };
++      };
++      fragment@6 {
++              target-path = "/clocks";
++              __overlay__ {
++                      clk_mcp251xfd_osc_1: mcp251xfd-spi0-1-osc {
++                              #clock-cells = <0>;
++                              compatible = "fixed-clock";
++                              clock-frequency = <40000000>;
++                      };
++              };
++      };
++      fragment@7 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      mcp251xfd@1 {
++                              compatible = "microchip,mcp251xfd";
++                              reg = <1>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&mcp251xfd_pins_1>;
++                              spi-max-frequency = <20000000>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
++                              clocks = <&clk_mcp251xfd_osc_1>;
++                      };
++              };
++      };
++      fragment@8 {
++              target = <&i2cbus>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      pcf85063@51 {
++                              compatible = "nxp,pcf85063";
++                              reg = <0x51>;
++                      };
++              };
++      };
++      fragment@9 {
++              target = <&i2c_arm>;
++              i2cbus: __overlay__ {
++                      status = "okay";
++              };
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1036-overlays-Rebuild-upstream-with-latest-ovmerge.patch b/target/linux/bcm27xx/patches-5.4/950-1036-overlays-Rebuild-upstream-with-latest-ovmerge.patch
new file mode 100644 (file)
index 0000000..b2e32cd
--- /dev/null
@@ -0,0 +1,173 @@
+From 6091a6c5536f422df652c4a14725de7dd1fc5e0f Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 30 Dec 2020 20:00:38 +0000
+Subject: [PATCH] overlays: Rebuild "upstream" with latest ovmerge
+
+The latest ovmerge drops disabled fragments, causing the "upstream"
+overlay to change.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ .../boot/dts/overlays/upstream-overlay.dts    | 38 +++++++------------
+ .../dts/overlays/upstream-pi4-overlay.dts     | 28 +-------------
+ 2 files changed, 15 insertions(+), 51 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/upstream-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts
+@@ -8,96 +8,84 @@
+ / {
+       compatible = "brcm,bcm2835";
+       fragment@0 {
+-              target = <&cma>;
+-              __dormant__ {
+-                      size = <0x10000000>;
+-              };
+-      };
+-      fragment@1 {
+               target = <&i2c2>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@2 {
++      fragment@1 {
+               target = <&fb>;
+               __overlay__ {
+                       status = "disabled";
+               };
+       };
+-      fragment@3 {
++      fragment@2 {
+               target = <&pixelvalve0>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@4 {
++      fragment@3 {
+               target = <&pixelvalve1>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@5 {
++      fragment@4 {
+               target = <&pixelvalve2>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@6 {
++      fragment@5 {
+               target = <&hvs>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@7 {
++      fragment@6 {
+               target = <&hdmi>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@8 {
++      fragment@7 {
+               target = <&v3d>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@9 {
++      fragment@8 {
+               target = <&vc4>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@10 {
++      fragment@9 {
+               target = <&clocks>;
+               __overlay__ {
+                       claim-clocks = <BCM2835_PLLD_DSI0 BCM2835_PLLD_DSI1 BCM2835_PLLH_AUX BCM2835_PLLH_PIX>;
+               };
+       };
+-      fragment@11 {
++      fragment@10 {
+               target = <&vec>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@12 {
++      fragment@11 {
+               target = <&txp>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@13 {
+-              target = <&hdmi>;
+-              __dormant__ {
+-                      dmas;
+-              };
+-      };
+-      fragment@14 {
++      fragment@12 {
+               target = <&audio>;
+               __overlay__ {
+                       brcm,disable-hdmi;
+               };
+       };
+-      fragment@15 {
++      fragment@13 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+--- a/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
++++ b/arch/arm/boot/dts/overlays/upstream-pi4-overlay.dts
+@@ -110,42 +110,18 @@
+               };
+       };
+       fragment@17 {
+-              target = <&hdmi0>;
+-              __dormant__ {
+-                      dmas;
+-              };
+-      };
+-      fragment@18 {
+-              target = <&hdmi1>;
+-              __dormant__ {
+-                      dmas;
+-              };
+-      };
+-      fragment@19 {
+               target = <&audio>;
+               __overlay__ {
+                       brcm,disable-hdmi;
+               };
+       };
+-      fragment@20 {
++      fragment@18 {
+               target = <&dvp>;
+               __overlay__ {
+                       status = "okay";
+               };
+       };
+-      fragment@21 {
+-              target = <&pixelvalve3>;
+-              __dormant__ {
+-                      status = "okay";
+-              };
+-      };
+-      fragment@22 {
+-              target = <&vec>;
+-              __dormant__ {
+-                      status = "okay";
+-              };
+-      };
+-      fragment@23 {
++      fragment@19 {
+               target = <&usb>;
+               #address-cells = <1>;
+               #size-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1037-overlays-give-Seeed-Studio-CAN-BUS-FD-HAT-a-v2-postf.patch b/target/linux/bcm27xx/patches-5.4/950-1037-overlays-give-Seeed-Studio-CAN-BUS-FD-HAT-a-v2-postf.patch
new file mode 100644 (file)
index 0000000..185c16c
--- /dev/null
@@ -0,0 +1,286 @@
+From 6b458078a50b9332e799e045f91c288a7ff8d8ca Mon Sep 17 00:00:00 2001
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+Date: Sat, 2 Jan 2021 21:08:59 +0100
+Subject: [PATCH] overlays: give Seeed Studio CAN BUS FD HAT a -v2
+ postfix
+
+There are several versions of the Seeed Studio CAN BUS FD HAT. This is the
+second version, based on the mcp2518fd, so give it a -v2 postfix.
+
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ arch/arm/boot/dts/overlays/Makefile                       | 2 +-
+ arch/arm/boot/dts/overlays/README                         | 8 ++++----
+ ...fd-hat-overlay.dts => seeed-can-fd-hat-v2-overlay.dts} | 0
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+ rename arch/arm/boot/dts/overlays/{seeed-can-fd-hat-overlay.dts => seeed-can-fd-hat-v2-overlay.dts} (100%)
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -159,7 +159,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       sc16is752-spi1.dtbo \
+       sdhost.dtbo \
+       sdio.dtbo \
+-      seeed-can-fd-hat.dtbo \
++      seeed-can-fd-hat-v2.dtbo \
+       sh1106-spi.dtbo \
+       smi.dtbo \
+       smi-dev.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2460,11 +2460,11 @@ Info:   This overlay is now deprecated.
+ Load:   <Deprecated>
+-Name:   seeed-can-fd-hat
+-Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels and an
+-        RTC.
++Name:   seeed-can-fd-hat-v2
++Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels
++        (based on the mcp2518fd) and an RTC.
+         https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html
+-Load:   dtoverlay=seeed-can-fd-hat
++Load:   dtoverlay=seeed-can-fd-hat-v2
+ Params: <None>
+--- a/arch/arm/boot/dts/overlays/seeed-can-fd-hat-overlay.dts
++++ /dev/null
+@@ -1,117 +0,0 @@
+-// redo: ovmerge -c mcp251xfd-overlay.dts,spi0-0,interrupt=25 mcp251xfd-overlay.dts,spi0-1,interrupt=24 i2c-rtc-overlay.dts,pcf85063
+-
+-// Device tree overlay for https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html 
+-
+-/dts-v1/;
+-/plugin/;
+-
+-#include <dt-bindings/gpio/gpio.h>
+-#include <dt-bindings/interrupt-controller/irq.h>
+-#include <dt-bindings/pinctrl/bcm2835.h>
+-
+-/ {
+-      compatible = "brcm,bcm2835";
+-      fragment@0 {
+-              target = <&spidev0>;
+-              __overlay__ {
+-                      status = "disabled";
+-              };
+-      };
+-      fragment@1 {
+-              target = <&gpio>;
+-              __overlay__ {
+-                      mcp251xfd_pins: mcp251xfd_spi0_0_pins {
+-                              brcm,pins = <25>;
+-                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
+-                      };
+-              };
+-      };
+-      fragment@2 {
+-              target-path = "/clocks";
+-              __overlay__ {
+-                      clk_mcp251xfd_osc: mcp251xfd-spi0-0-osc {
+-                              #clock-cells = <0>;
+-                              compatible = "fixed-clock";
+-                              clock-frequency = <40000000>;
+-                      };
+-              };
+-      };
+-      fragment@3 {
+-              target = <&spi0>;
+-              __overlay__ {
+-                      status = "okay";
+-                      #address-cells = <1>;
+-                      #size-cells = <0>;
+-                      mcp251xfd@0 {
+-                              compatible = "microchip,mcp251xfd";
+-                              reg = <0>;
+-                              pinctrl-names = "default";
+-                              pinctrl-0 = <&mcp251xfd_pins>;
+-                              spi-max-frequency = <20000000>;
+-                              interrupt-parent = <&gpio>;
+-                              interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+-                              clocks = <&clk_mcp251xfd_osc>;
+-                      };
+-              };
+-      };
+-      fragment@4 {
+-              target = <&spidev1>;
+-              __overlay__ {
+-                      status = "disabled";
+-              };
+-      };
+-      fragment@5 {
+-              target = <&gpio>;
+-              __overlay__ {
+-                      mcp251xfd_pins_1: mcp251xfd_spi0_1_pins {
+-                              brcm,pins = <24>;
+-                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
+-                      };
+-              };
+-      };
+-      fragment@6 {
+-              target-path = "/clocks";
+-              __overlay__ {
+-                      clk_mcp251xfd_osc_1: mcp251xfd-spi0-1-osc {
+-                              #clock-cells = <0>;
+-                              compatible = "fixed-clock";
+-                              clock-frequency = <40000000>;
+-                      };
+-              };
+-      };
+-      fragment@7 {
+-              target = <&spi0>;
+-              __overlay__ {
+-                      status = "okay";
+-                      #address-cells = <1>;
+-                      #size-cells = <0>;
+-                      mcp251xfd@1 {
+-                              compatible = "microchip,mcp251xfd";
+-                              reg = <1>;
+-                              pinctrl-names = "default";
+-                              pinctrl-0 = <&mcp251xfd_pins_1>;
+-                              spi-max-frequency = <20000000>;
+-                              interrupt-parent = <&gpio>;
+-                              interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+-                              clocks = <&clk_mcp251xfd_osc_1>;
+-                      };
+-              };
+-      };
+-      fragment@8 {
+-              target = <&i2cbus>;
+-              __overlay__ {
+-                      #address-cells = <1>;
+-                      #size-cells = <0>;
+-                      pcf85063@51 {
+-                              compatible = "nxp,pcf85063";
+-                              reg = <0x51>;
+-                      };
+-              };
+-      };
+-      fragment@9 {
+-              target = <&i2c_arm>;
+-              i2cbus: __overlay__ {
+-                      status = "okay";
+-              };
+-      };
+-};
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/seeed-can-fd-hat-v2-overlay.dts
+@@ -0,0 +1,117 @@
++// redo: ovmerge -c mcp251xfd-overlay.dts,spi0-0,interrupt=25 mcp251xfd-overlay.dts,spi0-1,interrupt=24 i2c-rtc-overlay.dts,pcf85063
++
++// Device tree overlay for https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html 
++
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/pinctrl/bcm2835.h>
++
++/ {
++      compatible = "brcm,bcm2835";
++      fragment@0 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++      fragment@1 {
++              target = <&gpio>;
++              __overlay__ {
++                      mcp251xfd_pins: mcp251xfd_spi0_0_pins {
++                              brcm,pins = <25>;
++                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
++                      };
++              };
++      };
++      fragment@2 {
++              target-path = "/clocks";
++              __overlay__ {
++                      clk_mcp251xfd_osc: mcp251xfd-spi0-0-osc {
++                              #clock-cells = <0>;
++                              compatible = "fixed-clock";
++                              clock-frequency = <40000000>;
++                      };
++              };
++      };
++      fragment@3 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      mcp251xfd@0 {
++                              compatible = "microchip,mcp251xfd";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&mcp251xfd_pins>;
++                              spi-max-frequency = <20000000>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
++                              clocks = <&clk_mcp251xfd_osc>;
++                      };
++              };
++      };
++      fragment@4 {
++              target = <&spidev1>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++      fragment@5 {
++              target = <&gpio>;
++              __overlay__ {
++                      mcp251xfd_pins_1: mcp251xfd_spi0_1_pins {
++                              brcm,pins = <24>;
++                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
++                      };
++              };
++      };
++      fragment@6 {
++              target-path = "/clocks";
++              __overlay__ {
++                      clk_mcp251xfd_osc_1: mcp251xfd-spi0-1-osc {
++                              #clock-cells = <0>;
++                              compatible = "fixed-clock";
++                              clock-frequency = <40000000>;
++                      };
++              };
++      };
++      fragment@7 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      mcp251xfd@1 {
++                              compatible = "microchip,mcp251xfd";
++                              reg = <1>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&mcp251xfd_pins_1>;
++                              spi-max-frequency = <20000000>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
++                              clocks = <&clk_mcp251xfd_osc_1>;
++                      };
++              };
++      };
++      fragment@8 {
++              target = <&i2cbus>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      pcf85063@51 {
++                              compatible = "nxp,pcf85063";
++                              reg = <0x51>;
++                      };
++              };
++      };
++      fragment@9 {
++              target = <&i2c_arm>;
++              i2cbus: __overlay__ {
++                      status = "okay";
++              };
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1038-overlays-Add-overlay-for-Seeed-Studio-CAN-BUS-FD-HAT.patch b/target/linux/bcm27xx/patches-5.4/950-1038-overlays-Add-overlay-for-Seeed-Studio-CAN-BUS-FD-HAT.patch
new file mode 100644 (file)
index 0000000..6ae1680
--- /dev/null
@@ -0,0 +1,192 @@
+From 42c792400770ec57cafce87cb9594a948d6c0700 Mon Sep 17 00:00:00 2001
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+Date: Sat, 2 Jan 2021 21:38:58 +0100
+Subject: [PATCH] overlays: Add overlay for Seeed Studio CAN BUS FD
+ HAT v1 (based on mcp2517fd)
+
+This patch adds the overlay for the Seeed Studio CAN BUS FD HAT v1 with two CAN
+FD Channels (based on mcp2517fd).
+
+https://www.seeedstudio.com/2-Channel-CAN-BUS-FD-Shield-for-Raspberry-Pi-p-4072.html
+
+The overlay was generated by:
+ovmerge -c spi1-1cs-overlay.dts,cs0_pin=18,cs0_spidev=false \
+           mcp251xfd-overlay.dts,spi0-0,interrupt=25 \
+           mcp251xfd-overlay.dts,spi1-0,interrupt=24
+
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ arch/arm/boot/dts/overlays/Makefile           |   1 +
+ arch/arm/boot/dts/overlays/README             |   8 +
+ .../overlays/seeed-can-fd-hat-v1-overlay.dts  | 138 ++++++++++++++++++
+ 3 files changed, 147 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/seeed-can-fd-hat-v1-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -159,6 +159,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       sc16is752-spi1.dtbo \
+       sdhost.dtbo \
+       sdio.dtbo \
++      seeed-can-fd-hat-v1.dtbo \
+       seeed-can-fd-hat-v2.dtbo \
+       sh1106-spi.dtbo \
+       smi.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2460,6 +2460,14 @@ Info:   This overlay is now deprecated.
+ Load:   <Deprecated>
++Name:   seeed-can-fd-hat-v1
++Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels
++        (based on the mcp2517fd).
++        https://www.seeedstudio.com/2-Channel-CAN-BUS-FD-Shield-for-Raspberry-Pi-p-4072.html
++Load:   dtoverlay=seeed-can-fd-hat-v1
++Params: <None>
++
++
+ Name:   seeed-can-fd-hat-v2
+ Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels
+         (based on the mcp2518fd) and an RTC.
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/seeed-can-fd-hat-v1-overlay.dts
+@@ -0,0 +1,138 @@
++// redo: ovmerge -c spi1-1cs-overlay.dts,cs0_pin=18,cs0_spidev=false mcp251xfd-overlay.dts,spi0-0,interrupt=25 mcp251xfd-overlay.dts,spi1-0,interrupt=24
++
++// Device tree overlay for https://www.seeedstudio.com/2-Channel-CAN-BUS-FD-Shield-for-Raspberry-Pi-p-4072.html
++
++/dts-v1/;
++/plugin/;
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/pinctrl/bcm2835.h>
++
++/ {
++      compatible = "brcm,bcm2835";
++      fragment@0 {
++              target = <&gpio>;
++              __overlay__ {
++                      spi1_pins: spi1_pins {
++                              brcm,pins = <19 20 21>;
++                              brcm,function = <3>;
++                      };
++                      spi1_cs_pins: spi1_cs_pins {
++                              brcm,pins = <18>;
++                              brcm,function = <1>;
++                      };
++              };
++      };
++      fragment@1 {
++              target = <&spi1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&spi1_pins &spi1_cs_pins>;
++                      cs-gpios = <&gpio 18 1>;
++                      status = "okay";
++                      spidev@0 {
++                              compatible = "spidev";
++                              reg = <0>;
++                              #address-cells = <1>;
++                              #size-cells = <0>;
++                              spi-max-frequency = <125000000>;
++                              status = "disabled";
++                      };
++              };
++      };
++      fragment@2 {
++              target = <&aux>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++      fragment@3 {
++              target = <&spidev0>;
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++      fragment@4 {
++              target = <&gpio>;
++              __overlay__ {
++                      mcp251xfd_pins: mcp251xfd_spi0_0_pins {
++                              brcm,pins = <25>;
++                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
++                      };
++              };
++      };
++      fragment@5 {
++              target-path = "/clocks";
++              __overlay__ {
++                      clk_mcp251xfd_osc: mcp251xfd-spi0-0-osc {
++                              #clock-cells = <0>;
++                              compatible = "fixed-clock";
++                              clock-frequency = <40000000>;
++                      };
++              };
++      };
++      fragment@6 {
++              target = <&spi0>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      mcp251xfd@0 {
++                              compatible = "microchip,mcp251xfd";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&mcp251xfd_pins>;
++                              spi-max-frequency = <20000000>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
++                              clocks = <&clk_mcp251xfd_osc>;
++                      };
++              };
++      };
++      fragment@7 {
++              target-path = "spi1/spidev@0";
++              __overlay__ {
++                      status = "disabled";
++              };
++      };
++      fragment@8 {
++              target = <&gpio>;
++              __overlay__ {
++                      mcp251xfd_pins_1: mcp251xfd_spi1_0_pins {
++                              brcm,pins = <24>;
++                              brcm,function = <BCM2835_FSEL_GPIO_IN>;
++                      };
++              };
++      };
++      fragment@9 {
++              target-path = "/clocks";
++              __overlay__ {
++                      clk_mcp251xfd_osc_1: mcp251xfd-spi1-0-osc {
++                              #clock-cells = <0>;
++                              compatible = "fixed-clock";
++                              clock-frequency = <40000000>;
++                      };
++              };
++      };
++      fragment@10 {
++              target = <&spi1>;
++              __overlay__ {
++                      status = "okay";
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      mcp251xfd@0 {
++                              compatible = "microchip,mcp251xfd";
++                              reg = <0>;
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&mcp251xfd_pins_1>;
++                              spi-max-frequency = <20000000>;
++                              interrupt-parent = <&gpio>;
++                              interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
++                              clocks = <&clk_mcp251xfd_osc_1>;
++                      };
++              };
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1039-overlays-add-wm8960-soundcard-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-1039-overlays-add-wm8960-soundcard-overlay.patch
new file mode 100644 (file)
index 0000000..fa2f54c
--- /dev/null
@@ -0,0 +1,129 @@
+From 4b26aad69c65e141e7ad5187c558d20304eb4bd8 Mon Sep 17 00:00:00 2001
+From: Aaron Shaw <shawaj@gmail.com>
+Date: Sat, 2 Jan 2021 02:34:03 +0000
+Subject: [PATCH] overlays: add wm8960-soundcard overlay
+
+add overlay for waveshare wm8960 simple-audio-card
+
+Change-type: patch
+Signed-off-by: Aaron Shaw <shawaj@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  3 +-
+ arch/arm/boot/dts/overlays/README             |  7 ++
+ .../dts/overlays/wm8960-soundcard-overlay.dts | 82 +++++++++++++++++++
+ 3 files changed, 91 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/overlays/wm8960-soundcard-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -210,7 +210,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       w1-gpio.dtbo \
+       w1-gpio-pullup.dtbo \
+       w5500.dtbo \
+-      wittypi.dtbo
++      wittypi.dtbo \
++      wm8960-soundcard.dtbo
+ targets += dtbs dtbs_install
+ targets += $(dtbo-y)
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -3073,6 +3073,13 @@ Params: led_gpio                GPIO for
+                                 "default-on")
++Name:   wm8960-soundcard
++Info:   Overlay for the Waveshare wm8960 soundcard
++Load:   dtoverlay=wm8960-soundcard,<param>=<val>
++Params: alsaname                Changes the card name in ALSA
++        compatible              Changes the codec compatibility
++
++
+ Troubleshooting
+ ===============
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/wm8960-soundcard-overlay.dts
+@@ -0,0 +1,82 @@
++// Definitions for Waveshare WM8960 https://github.com/waveshare/WM8960-Audio-HAT
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target-path="/";
++              __overlay__ {
++                      wm8960_mclk: wm8960_mclk {
++                              compatible = "fixed-clock";
++                              #clock-cells = <0>;
++                              clock-frequency = <12288000>;
++                      };
++              };
++      };
++      fragment@2 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      wm8960: wm8960 {
++                              compatible = "wlf,wm8960";
++                              reg = <0x1a>;
++                              #sound-dai-cells = <0>;
++                              AVDD-supply = <&vdd_5v0_reg>;
++                              DVDD-supply = <&vdd_3v3_reg>;
++                      };
++              };
++      };
++
++
++      fragment@3 {
++              target = <&sound>;
++              slave_overlay: __overlay__ {
++                      compatible = "simple-audio-card";
++                      simple-audio-card,format = "i2s";
++                      simple-audio-card,name = "wm8960-soundcard"; 
++                      status = "okay";
++
++                      simple-audio-card,widgets =
++                              "Microphone", "Mic Jack",
++                              "Line", "Line In",
++                              "Line", "Line Out",
++                              "Speaker", "Speaker",
++                              "Headphone", "Headphone Jack";
++                      simple-audio-card,routing =
++                              "Headphone Jack", "HP_L",
++                              "Headphone Jack", "HP_R",
++                              "Speaker", "SPK_LP",
++                              "Speaker", "SPK_LN",
++                              "LINPUT1", "Mic Jack",
++                              "LINPUT3", "Mic Jack",
++                              "RINPUT1", "Mic Jack",
++                              "RINPUT2", "Mic Jack";
++
++                      simple-audio-card,cpu {
++                              sound-dai = <&i2s>;
++                      };
++                      dailink0_slave: simple-audio-card,codec {
++                              sound-dai = <&wm8960>;
++                              clocks = <&wm8960_mclk>;
++                              clock-names = "mclk";
++                      };
++              };
++      };
++
++      __overrides__ {
++              alsaname = <&slave_overlay>,"simple-audio-card,name";
++              compatible = <&wm8960>,"compatible";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1040-overlays-add-spi-override-to-merus-amp-overlay.patch b/target/linux/bcm27xx/patches-5.4/950-1040-overlays-add-spi-override-to-merus-amp-overlay.patch
new file mode 100644 (file)
index 0000000..213d293
--- /dev/null
@@ -0,0 +1,44 @@
+From 2b4ffcc3d1a589154928830e56d4b8efdf15e368 Mon Sep 17 00:00:00 2001
+From: Aaron Shaw <shawaj@gmail.com>
+Date: Sat, 26 Dec 2020 03:13:14 +0000
+Subject: [PATCH] overlays: add spi override to merus-amp overlay
+
+adds an override to the merus-amp overlay to turn the spi bus off
+
+Change-type: patch
+Signed-off-by: Aaron Shaw <shawaj@gmail.com>
+---
+ arch/arm/boot/dts/overlays/README                |  4 ++--
+ arch/arm/boot/dts/overlays/merus-amp-overlay.dts | 10 ++++++++++
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1870,8 +1870,8 @@ Params: speed                   Display
+ Name:   merus-amp
+ Info:   Configures the merus-amp audio card
+-Load:   dtoverlay=merus-amp
+-Params: <None>
++Load:   dtoverlay=merus-amp,<param>=<val>
++Params: spioff                  Turn SPI bus off
+ Name:   midi-uart0
+--- a/arch/arm/boot/dts/overlays/merus-amp-overlay.dts
++++ b/arch/arm/boot/dts/overlays/merus-amp-overlay.dts
+@@ -57,4 +57,14 @@
+                       status = "okay";
+               };
+       };
++
++      fragment@4 {
++              target = <&spi0>;
++              frag4: __overlay__ {
++              };
++      };
++
++      __overrides__ {
++              spioff = <&frag4>, "status=disabled";
++      };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-1041-overlays-seeed-can-fd-hat-clarify-how-to-identify-HA.patch b/target/linux/bcm27xx/patches-5.4/950-1041-overlays-seeed-can-fd-hat-clarify-how-to-identify-HA.patch
new file mode 100644 (file)
index 0000000..d622888
--- /dev/null
@@ -0,0 +1,45 @@
+From 426116286821ed9ce10e415ffdebb2c55e728050 Mon Sep 17 00:00:00 2001
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+Date: Sat, 9 Jan 2021 17:03:32 +0100
+Subject: [PATCH] overlays: seeed-can-fd-hat: clarify how to identify
+ HAT version
+
+It turns out the used CAN SPI chip is not a good way to identify the version of
+the CAN HAT.
+
+There are two different board layouts of the Seeed Studio CAN BUS FD HAT. The
+v1 board doesn't have a battery holder, while the v2 board has. Update the
+overlay README accordinly.
+
+Link: https://github.com/Seeed-Studio/seeed-linux-dtoverlays/issues/13
+Cc: Patrick Menschel <menschel.p@posteo.de>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ arch/arm/boot/dts/overlays/README | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -2461,16 +2461,18 @@ Load:   <Deprecated>
+ Name:   seeed-can-fd-hat-v1
+-Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels
+-        (based on the mcp2517fd).
++Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD
++        channels without RTC. Use this overlay if your HAT has no
++        battery holder.
+         https://www.seeedstudio.com/2-Channel-CAN-BUS-FD-Shield-for-Raspberry-Pi-p-4072.html
+ Load:   dtoverlay=seeed-can-fd-hat-v1
+ Params: <None>
+ Name:   seeed-can-fd-hat-v2
+-Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD channels
+-        (based on the mcp2518fd) and an RTC.
++Info:   Overlay for Seeed Studio CAN BUS FD HAT with two CAN FD
++        channels and an RTC. Use this overlay if your HAT has a
++        battery holder.
+         https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html
+ Load:   dtoverlay=seeed-can-fd-hat-v2
+ Params: <None>
diff --git a/target/linux/bcm27xx/patches-5.4/950-1042-uapi-bcm2835-isp-Add-colour-denoise-configuration.patch b/target/linux/bcm27xx/patches-5.4/950-1042-uapi-bcm2835-isp-Add-colour-denoise-configuration.patch
new file mode 100644 (file)
index 0000000..48ffc01
--- /dev/null
@@ -0,0 +1,56 @@
+From b920f23b301503d6127f3fcdc3c88e24aa470679 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Thu, 14 Jan 2021 09:18:42 +0000
+Subject: [PATCH] uapi: bcm2835-isp: Add colour denoise configuration
+
+Add a configuration structure for colour denoise to the bcm2835_isp
+driver.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ include/uapi/linux/bcm2835-isp.h | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/include/uapi/linux/bcm2835-isp.h
++++ b/include/uapi/linux/bcm2835-isp.h
+@@ -31,6 +31,8 @@
+                               (V4L2_CID_USER_BCM2835_ISP_BASE + 0x0007)
+ #define V4L2_CID_USER_BCM2835_ISP_DPC         \
+                               (V4L2_CID_USER_BCM2835_ISP_BASE + 0x0008)
++#define V4L2_CID_USER_BCM2835_ISP_CDN \
++                              (V4L2_CID_USER_BCM2835_ISP_BASE + 0x0009)
+ /*
+  * All structs below are directly mapped onto the equivalent structs in
+@@ -176,6 +178,31 @@ struct bcm2835_isp_gamma {
+ };
+ /**
++ * enum bcm2835_isp_cdn_mode - Mode of operation for colour denoise.
++ *
++ * @CDN_MODE_FAST:            Fast (but lower quality) colour denoise
++ *                            algorithm, typically used for video recording.
++ * @CDN_HIGH_QUALITY:         High quality (but slower) colour denoise
++ *                            algorithm, typically used for stills capture.
++ */
++enum bcm2835_isp_cdn_mode {
++      CDN_MODE_FAST = 0,
++      CDN_MODE_HIGH_QUALITY = 1,
++};
++
++/**
++ * struct bcm2835_isp_cdn - Colour denoise parameters set with the
++ *                        V4L2_CID_USER_BCM2835_ISP_CDN ctrl.
++ *
++ * @enabled:  Enable colour denoise.
++ * @mode:     Colour denoise operating mode (see enum &bcm2835_isp_cdn_mode)
++ */
++struct bcm2835_isp_cdn {
++      __u32 enabled;
++      __u32 mode;
++};
++
++/**
+  * struct bcm2835_isp_denoise - Denoise parameters set with the
+  *                            V4L2_CID_USER_BCM2835_ISP_DENOISE ctrl.
+  *
diff --git a/target/linux/bcm27xx/patches-5.4/950-1043-staging-vc04_services-ISP-Add-colour-denoise-control.patch b/target/linux/bcm27xx/patches-5.4/950-1043-staging-vc04_services-ISP-Add-colour-denoise-control.patch
new file mode 100644 (file)
index 0000000..6df7a0c
--- /dev/null
@@ -0,0 +1,75 @@
+From 29ec709794ac2aae569c8d486dd19a7d731cfeeb Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Thu, 14 Jan 2021 09:20:52 +0000
+Subject: [PATCH] staging: vc04_services: ISP: Add colour denoise
+ control
+
+Add colour denoise control to the bcm2835 driver through a new v4l2
+control: V4L2_CID_USER_BCM2835_ISP_CDN.
+
+Add the accompanying MMAL configuration structure definitions as well.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ .../vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c    |  5 +++++
+ .../vc04_services/bcm2835-isp/bcm2835_isp_ctrls.h   |  5 +++++
+ .../vc04_services/vchiq-mmal/mmal-parameters.h      | 13 +++++++++++++
+ 3 files changed, 23 insertions(+)
+
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c
+@@ -776,6 +776,11 @@ static int bcm2835_isp_s_ctrl(struct v4l
+                                   ctrl->p_new.p_u8,
+                                   sizeof(struct bcm2835_isp_denoise));
+               break;
++      case V4L2_CID_USER_BCM2835_ISP_CDN:
++              ret = set_isp_param(node, MMAL_PARAMETER_CDN,
++                                  ctrl->p_new.p_u8,
++                                  sizeof(struct bcm2835_isp_cdn));
++              break;
+       case V4L2_CID_USER_BCM2835_ISP_SHARPEN:
+               ret = set_isp_param(node, MMAL_PARAMETER_SHARPEN,
+                                   ctrl->p_new.p_u8,
+--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_ctrls.h
++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835_isp_ctrls.h
+@@ -57,6 +57,11 @@ static const struct bcm2835_isp_custom_c
+               .size   = sizeof(struct bcm2835_isp_denoise),
+               .flags  = 0
+       }, {
++              .name   = "Colour Denoise",
++              .id     = V4L2_CID_USER_BCM2835_ISP_CDN,
++              .size   = sizeof(struct bcm2835_isp_cdn),
++              .flags  = 0
++      }, {
+               .name   = "Defective Pixel Correction",
+               .id     = V4L2_CID_USER_BCM2835_ISP_DPC,
+               .size   = sizeof(struct bcm2835_isp_dpc),
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -277,6 +277,8 @@ enum mmal_parameter_camera_type {
+       MMAL_PARAMETER_DPC,
+               /**< Tales a @ref MMAP_PARAMETER_GAMMA_T */
+       MMAL_PARAMETER_GAMMA,
++              /**< Takes a @ref MMAL_PARAMETER_CDN_T */
++      MMAL_PARAMETER_CDN,
+ };
+ struct mmal_parameter_rational {
+@@ -910,6 +912,17 @@ struct mmal_parameter_gamma {
+       u16 y[MMAL_NUM_GAMMA_PTS];
+ };
++enum mmal_parameter_cdn_mode {
++      MMAL_PARAM_CDN_FAST = 0,
++      MMAL_PARAM_CDN_HIGH_QUALITY = 1,
++      MMAL_PARAM_CDN_DUMMY  = 0x7FFFFFFF
++};
++
++struct mmal_parameter_colour_denoise {
++      u32 enabled;
++      enum mmal_parameter_cdn_mode mode;
++};
++
+ struct mmal_parameter_denoise {
+       u32 enabled;
+       u32 constant;
diff --git a/target/linux/bcm27xx/patches-5.4/950-1044-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch b/target/linux/bcm27xx/patches-5.4/950-1044-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch
new file mode 100644 (file)
index 0000000..24292fe
--- /dev/null
@@ -0,0 +1,31 @@
+From 6f36a21e2a77b33eed45159a1556a4dd77422976 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Fri, 29 Jan 2021 10:34:11 +0000
+Subject: [PATCH] kbuild: Silence unavoidable dtc overlay warnings
+
+Much effort has been put into finding ways to avoid warnings from dtc
+about overlays, usually to do with the presence of #address-cells and
+size-cells, but not exclusively so. Since the issues being warned about
+are harmless, suppress the warnings to declutter the build output and
+to avoid alarming users.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ scripts/Makefile.lib | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -306,6 +306,12 @@ cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ;
+       $(DTC) -@ -H epapr -O dtb -o $@ -b 0 \
+               -i $(dir $<) $(DTC_FLAGS) \
+               -Wno-interrupts_property \
++              -Wno-label_is_string \
++              -Wno-reg_format \
++              -Wno-pci_device_bus_num \
++              -Wno-i2c_bus_reg \
++              -Wno-spi_bus_reg \
++              -Wno-avoid_default_addr_size \
+               -d $(depfile).dtc.tmp $(dtc-tmp) ; \
+       cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
diff --git a/target/linux/bcm27xx/patches-5.4/950-1045-Adds-the-DT-overlays-to-support-Hifiberry-AMP100.patch b/target/linux/bcm27xx/patches-5.4/950-1045-Adds-the-DT-overlays-to-support-Hifiberry-AMP100.patch
new file mode 100644 (file)
index 0000000..24ff1b3
--- /dev/null
@@ -0,0 +1,132 @@
+From d689ccf52fb81664b7eccb91dc05a93d64ba793c Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joerg@i2audio.com>
+Date: Fri, 29 Jan 2021 08:26:44 +0100
+Subject: [PATCH] Adds the DT-overlays to support Hifiberry AMP100
+
+Adds new DT-overlay to control AMP100.
+
+Signed-off-by: Joerg Schambacher <joerg@hifiberry.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |  1 +
+ arch/arm/boot/dts/overlays/README             | 30 ++++++++-
+ .../dts/overlays/hifiberry-amp100-overlay.dts | 64 +++++++++++++++++++
+ 3 files changed, 94 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp100-overlay.dts
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -60,6 +60,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       hd44780-lcd.dtbo \
+       hdmi-backlight-hwhack-gpio.dtbo \
+       hifiberry-amp.dtbo \
++      hifiberry-amp100.dtbo \
+       hifiberry-dac.dtbo \
+       hifiberry-dacplus.dtbo \
+       hifiberry-dacplusadc.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1045,8 +1045,36 @@ Load:   dtoverlay=hifiberry-amp
+ Params: <None>
++Name:   hifiberry-amp100
++Info:   Configures the HifiBerry AMP100 audio card
++Load:   dtoverlay=hifiberry-amp100,<param>=<val>
++Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
++                                Digital volume control. Enable with
++                                "dtoverlay=hifiberry-amp100,24db_digital_gain"
++                                (The default behaviour is that the Digital
++                                volume control is limited to a maximum of
++                                0dB. ie. it can attenuate but not provide
++                                gain. For most users, this will be desired
++                                as it will prevent clipping. By appending
++                                the 24dB_digital_gain parameter, the Digital
++                                volume control will allow up to 24dB of
++                                gain. If this parameter is enabled, it is the
++                                responsibility of the user to ensure that
++                                the Digital volume control is set to a value
++                                that does not result in clipping/distortion!)
++        slave                   Force DAC+ Pro into slave mode, using Pi as
++                                master for bit clock and frame clock.
++        leds_off                If set to 'true' the onboard indicator LEDs
++                                are switched off at all times.
++        auto_mute               If set to 'true' the amplifier is automatically
++                                muted when the DAC is not playing.
++        mute_ext_ctl            The amplifier's HW mute control is enabled
++                                in ALSA mixer and set to <val>.
++                                Will be overwritten by ALSA user settings.
++
++
+ Name:   hifiberry-dac
+-Info:   Configures the HifiBerry DAC audio card
++Info:   Configures the HifiBerry DAC audio cards
+ Load:   dtoverlay=hifiberry-dac
+ Params: <None>
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/hifiberry-amp100-overlay.dts
+@@ -0,0 +1,64 @@
++// Definitions for HiFiBerry AMP100
++/dts-v1/;
++/plugin/;
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target-path = "/";
++              __overlay__ {
++                      dacpro_osc: dacpro_osc {
++                              compatible = "hifiberry,dacpro-clk";
++                              #clock-cells = <0>;
++                      };
++              };
++      };
++
++      fragment@1 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      pcm5122@4d {
++                              #sound-dai-cells = <0>;
++                              compatible = "ti,pcm5122";
++                              reg = <0x4d>;
++                              clocks = <&dacpro_osc>;
++                              AVDD-supply = <&vdd_3v3_reg>;
++                              DVDD-supply = <&vdd_3v3_reg>;
++                              CPVDD-supply = <&vdd_3v3_reg>;
++                              status = "okay";
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&sound>;
++              hifiberry_dacplus: __overlay__ {
++                      compatible = "hifiberry,hifiberry-dacplus";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++                      mute-gpio = <&gpio 4 0>;
++                      reset-gpio = <&gpio 17 0x11>;
++              };
++      };
++
++      __overrides__ {
++              24db_digital_gain =
++                      <&hifiberry_dacplus>,"hifiberry,24db_digital_gain?";
++              slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?";
++              leds_off = <&hifiberry_dacplus>,"hifiberry-dacplus,leds_off?";
++              mute_ext_ctl = <&hifiberry_dacplus>,"hifiberry-dacplus,mute_ext_ctl:0";
++              auto_mute = <&hifiberry_dacplus>,"hifiberry-dacplus,auto_mute?";
++      };
++};
diff --git a/target/linux/bcm27xx/patches-5.4/950-1046-Enhances-the-Hifiberry-DAC-driver-for-Hifiberry-AMP1.patch b/target/linux/bcm27xx/patches-5.4/950-1046-Enhances-the-Hifiberry-DAC-driver-for-Hifiberry-AMP1.patch
new file mode 100644 (file)
index 0000000..4e15285
--- /dev/null
@@ -0,0 +1,238 @@
+From 0b584f3c2808dba8dc9e74a628b65008302804a5 Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joerg@i2audio.com>
+Date: Fri, 29 Jan 2021 16:16:39 +0100
+Subject: [PATCH] Enhances the Hifiberry DAC+ driver for Hifiberry
+ AMP100 support
+
+Adds the necessary GPIO handling and ALSA mixer extensions.
+Also fixes a problem with the PLL/CLK control when switching sample rates.
+Thanks to Clive Messer for the support!
+
+Signed-off-by: Joerg Schambacher <joerg@hifiberry.com>
+---
+ sound/soc/bcm/hifiberry_dacplus.c | 124 ++++++++++++++++++++++++++----
+ 1 file changed, 111 insertions(+), 13 deletions(-)
+
+--- a/sound/soc/bcm/hifiberry_dacplus.c
++++ b/sound/soc/bcm/hifiberry_dacplus.c
+@@ -1,10 +1,10 @@
+ /*
+- * ASoC Driver for HiFiBerry DAC+ / DAC Pro
++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro / AMP100
+  *
+  * Author:    Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
+  *            Copyright 2014-2015
+  *            based on code by Florian Meier <florian.meier@koalo.de>
+- *            Headphone added by Joerg Schambacher, joerg@i2audio.com
++ *            Headphone/AMP100 Joerg Schambacher <joerg@hifiberry.com>
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+@@ -17,6 +17,8 @@
+  */
+ #include <linux/module.h>
++#include <linux/gpio/consumer.h>
++#include <../drivers/gpio/gpiolib.h>
+ #include <linux/platform_device.h>
+ #include <linux/kernel.h>
+ #include <linux/clk.h>
+@@ -53,6 +55,47 @@ static bool slave;
+ static bool snd_rpi_hifiberry_is_dacpro;
+ static bool digital_gain_0db_limit = true;
+ static bool leds_off;
++static bool auto_mute;
++static int mute_ext_ctl;
++static int mute_ext;
++static struct gpio_desc *snd_mute_gpio;
++static struct gpio_desc *snd_reset_gpio;
++static struct snd_soc_card snd_rpi_hifiberry_dacplus;
++
++static int snd_rpi_hifiberry_dacplus_mute_set(int mute)
++{
++      gpiod_set_value_cansleep(snd_mute_gpio, mute);
++      return 1;
++}
++
++static int snd_rpi_hifiberry_dacplus_mute_get(struct snd_kcontrol *kcontrol,
++                              struct snd_ctl_elem_value *ucontrol)
++{
++      ucontrol->value.integer.value[0] = mute_ext;
++
++      return 0;
++}
++
++static int snd_rpi_hifiberry_dacplus_mute_put(struct snd_kcontrol *kcontrol,
++                              struct snd_ctl_elem_value *ucontrol)
++{
++      if (mute_ext == ucontrol->value.integer.value[0])
++              return 0;
++
++      mute_ext = ucontrol->value.integer.value[0];
++
++      return snd_rpi_hifiberry_dacplus_mute_set(mute_ext);
++}
++
++static const char * const mute_text[] = {"Play", "Mute"};
++static const struct soc_enum hb_dacplus_opt_mute_enum =
++      SOC_ENUM_SINGLE_EXT(2, mute_text);
++
++static const struct snd_kcontrol_new hb_dacplus_opt_mute_controls[] = {
++      SOC_ENUM_EXT("Mute(ext)", hb_dacplus_opt_mute_enum,
++                            snd_rpi_hifiberry_dacplus_mute_get,
++                            snd_rpi_hifiberry_dacplus_mute_put),
++};
+ static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_component *component,
+       int clk_id)
+@@ -68,6 +111,7 @@ static void snd_rpi_hifiberry_dacplus_se
+               snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
+               break;
+       }
++      usleep_range(2000, 2100);
+ }
+ static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_component *component)
+@@ -85,13 +129,6 @@ static bool snd_rpi_hifiberry_dacplus_is
+       return (!(sck & 0x40));
+ }
+-static bool snd_rpi_hifiberry_dacplus_is_sclk_sleep(
+-      struct snd_soc_component *component)
+-{
+-      msleep(2);
+-      return snd_rpi_hifiberry_dacplus_is_sclk(component);
+-}
+-
+ static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_component *component)
+ {
+       bool isClk44EN, isClk48En, isNoClk;
+@@ -99,13 +136,13 @@ static bool snd_rpi_hifiberry_dacplus_is
+       snd_rpi_hifiberry_dacplus_clk_gpio(component);
+       snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
+-      isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk_sleep(component);
++      isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk(component);
+       snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
+-      isNoClk = snd_rpi_hifiberry_dacplus_is_sclk_sleep(component);
++      isNoClk = snd_rpi_hifiberry_dacplus_is_sclk(component);
+       snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
+-      isClk48En = snd_rpi_hifiberry_dacplus_is_sclk_sleep(component);
++      isClk48En = snd_rpi_hifiberry_dacplus_is_sclk(component);
+       return (isClk44EN && isClk48En && !isNoClk);
+ }
+@@ -149,6 +186,7 @@ static int snd_rpi_hifiberry_dacplus_ini
+ {
+       struct snd_soc_component *component = rtd->codec_dai->component;
+       struct pcm512x_priv *priv;
++      struct snd_soc_card *card = &snd_rpi_hifiberry_dacplus;
+       if (slave)
+               snd_rpi_hifiberry_is_dacpro = false;
+@@ -187,6 +225,20 @@ static int snd_rpi_hifiberry_dacplus_ini
+               if (ret < 0)
+                       dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
+       }
++      if (snd_reset_gpio) {
++              gpiod_set_value_cansleep(snd_reset_gpio, 0);
++              msleep(1);
++              gpiod_set_value_cansleep(snd_reset_gpio, 1);
++              msleep(1);
++              gpiod_set_value_cansleep(snd_reset_gpio, 0);
++      }
++
++      if (mute_ext_ctl)
++              snd_soc_add_card_controls(card, hb_dacplus_opt_mute_controls,
++                              ARRAY_SIZE(hb_dacplus_opt_mute_controls));
++
++      if (snd_mute_gpio)
++              gpiod_set_value_cansleep(snd_mute_gpio, mute_ext);
+       return 0;
+ }
+@@ -254,6 +306,8 @@ static int snd_rpi_hifiberry_dacplus_sta
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_component *component = rtd->codec_dai->component;
++      if (auto_mute)
++              gpiod_set_value_cansleep(snd_mute_gpio, 0);
+       if (leds_off)
+               return 0;
+       snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
+@@ -267,6 +321,8 @@ static void snd_rpi_hifiberry_dacplus_sh
+       struct snd_soc_component *component = rtd->codec_dai->component;
+       snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
++      if (auto_mute)
++              gpiod_set_value_cansleep(snd_mute_gpio, 1);
+ }
+ /* machine stream operations */
+@@ -342,6 +398,8 @@ static int snd_rpi_hifiberry_dacplus_pro
+       struct device_node *tpa_node;
+       struct property *tpa_prop;
+       struct of_changeset ocs;
++      struct property *pp;
++      int tmp;
+       /* probe for head phone amp */
+       ret = hb_hp_detect();
+@@ -396,6 +454,39 @@ static int snd_rpi_hifiberry_dacplus_pro
+                                               "hifiberry-dacplus,slave");
+               leds_off = of_property_read_bool(pdev->dev.of_node,
+                                               "hifiberry-dacplus,leds_off");
++              auto_mute = of_property_read_bool(pdev->dev.of_node,
++                                              "hifiberry-dacplus,auto_mute");
++
++              /*
++               * check for HW MUTE as defined in DT-overlay
++               * active high, therefore default to HIGH to MUTE
++               */
++              snd_mute_gpio = devm_gpiod_get_optional(&pdev->dev,
++                                               "mute", GPIOD_OUT_HIGH);
++              if (IS_ERR(snd_mute_gpio)) {
++                      dev_err(&pdev->dev, "Can't allocate GPIO (HW-MUTE)");
++                      return PTR_ERR(snd_mute_gpio);
++              }
++
++              /* add ALSA control if requested in DT-overlay (AMP100) */
++              pp = of_find_property(pdev->dev.of_node,
++                              "hifiberry-dacplus,mute_ext_ctl", &tmp);
++              if (pp) {
++                      if (!of_property_read_u32(pdev->dev.of_node,
++                              "hifiberry-dacplus,mute_ext_ctl", &mute_ext)) {
++                              /* ALSA control will be used */
++                              mute_ext_ctl = 1;
++                      }
++              }
++
++              /* check for HW RESET (AMP100) */
++              snd_reset_gpio = devm_gpiod_get_optional(&pdev->dev,
++                                              "reset", GPIOD_OUT_HIGH);
++              if (IS_ERR(snd_reset_gpio)) {
++                      dev_err(&pdev->dev, "Can't allocate GPIO (HW-RESET)");
++                      return PTR_ERR(snd_reset_gpio);
++              }
++
+       }
+       ret = devm_snd_soc_register_card(&pdev->dev,
+@@ -403,7 +494,14 @@ static int snd_rpi_hifiberry_dacplus_pro
+       if (ret && ret != -EPROBE_DEFER)
+               dev_err(&pdev->dev,
+                       "snd_soc_register_card() failed: %d\n", ret);
+-
++      if (!ret) {
++              if (snd_mute_gpio)
++                      dev_info(&pdev->dev, "GPIO%i for HW-MUTE selected",
++                                      gpio_chip_hwgpio(snd_mute_gpio));
++              if (snd_reset_gpio)
++                      dev_info(&pdev->dev, "GPIO%i for HW-RESET selected",
++                                      gpio_chip_hwgpio(snd_reset_gpio));
++      }
+       return ret;
+ }
diff --git a/target/linux/bcm27xx/patches-5.4/950-1047-ARM-dts-Declare-Pi400-and-CM4-have-no-audio-pins.patch b/target/linux/bcm27xx/patches-5.4/950-1047-ARM-dts-Declare-Pi400-and-CM4-have-no-audio-pins.patch
new file mode 100644 (file)
index 0000000..c7d7c66
--- /dev/null
@@ -0,0 +1,41 @@
+From 747df57eabbe2e3b5bd47e268aa42658a57749ca Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Wed, 3 Feb 2021 16:23:43 +0000
+Subject: [PATCH] ARM: dts: Declare Pi400 and CM4 have no audio pins
+
+The audio_pins node is left as a placeholder for the audremap overlay,
+and it must have (empty) brcm,function and brcm,pins properties
+otherwise it will be rejected by the pinctrl driver.
+
+See: https://www.raspberrypi.org/forums/viewtopic.php?f=98&t=301891
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi-400.dts | 4 ++--
+ arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 2 ++
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi-400.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-400.dts
+@@ -495,8 +495,8 @@
+ &gpio {
+       audio_pins: audio_pins {
+-              brcm,pins = <40 41>;
+-              brcm,function = <4>;
++              brcm,pins = <>;
++              brcm,function = <>;
+       };
+ };
+--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts
+@@ -434,6 +434,8 @@
+ &gpio {
+       audio_pins: audio_pins {
++              brcm,pins = <>;
++              brcm,function = <>;
+       };
+ };
diff --git a/target/linux/bcm27xx/patches-5.4/950-1048-Hifiberry-DAC-ADC-Pro-fix-for-the-PLL-when-changing-.patch b/target/linux/bcm27xx/patches-5.4/950-1048-Hifiberry-DAC-ADC-Pro-fix-for-the-PLL-when-changing-.patch
new file mode 100644 (file)
index 0000000..47ecb8b
--- /dev/null
@@ -0,0 +1,56 @@
+From c70ae3d1923339746d156bd1d723d141113183aa Mon Sep 17 00:00:00 2001
+From: Joerg Schambacher <joerg@i2audio.com>
+Date: Mon, 1 Feb 2021 16:53:46 +0100
+Subject: [PATCH] Hifiberry DAC+ADC Pro fix for the PLL when changing
+ sample rates
+
+Adds 2 msecs delay when switching between oscillators to allow
+correct PLL settling.
+Thanks to Clive Messer for the support!
+
+Signed-off-by: Joerg Schambacher <joerg@hifiberry.com>
+---
+ sound/soc/bcm/hifiberry_dacplusadcpro.c | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+--- a/sound/soc/bcm/hifiberry_dacplusadcpro.c
++++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
+@@ -190,6 +190,7 @@ static void snd_rpi_hifiberry_dacplusadc
+                               PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
+               break;
+       }
++      usleep_range(2000, 2100);
+ }
+ static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
+@@ -207,13 +208,6 @@ static bool snd_rpi_hifiberry_dacplusadc
+       return (!(sck & 0x40));
+ }
+-static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(
+-      struct snd_soc_component *component)
+-{
+-      msleep(2);
+-      return snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
+-}
+-
+ static bool snd_rpi_hifiberry_dacplusadcpro_is_pro_card(struct snd_soc_component *component)
+ {
+       bool isClk44EN, isClk48En, isNoClk;
+@@ -221,13 +215,13 @@ static bool snd_rpi_hifiberry_dacplusadc
+       snd_rpi_hifiberry_dacplusadcpro_clk_gpio(component);
+       snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
+-      isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++      isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
+       snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
+-      isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++      isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
+       snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
+-      isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk_sleep(component);
++      isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
+       return (isClk44EN && isClk48En && !isNoClk);
+ }